mirror of
https://github.com/Such-Software/xmrcheckout.git
synced 2026-10-17 05:51:34 +02:00
docs: add non-Docker deployment and optional reverse proxy
This commit is contained in:
@@ -16,6 +16,7 @@ This project is intentionally conservative by design:
|
|||||||
- [Screenshots](#screenshots)
|
- [Screenshots](#screenshots)
|
||||||
- [Quick start](#quick-start)
|
- [Quick start](#quick-start)
|
||||||
- [Self-hosted deployment](#self-hosted-deployment-docker-compose)
|
- [Self-hosted deployment](#self-hosted-deployment-docker-compose)
|
||||||
|
- [Self-hosted deployment (no Docker)](#self-hosted-deployment-no-docker)
|
||||||
- [Development (API)](#development-api-python)
|
- [Development (API)](#development-api-python)
|
||||||
|
|
||||||
## What it does
|
## What it does
|
||||||
@@ -42,7 +43,7 @@ What it does not do:
|
|||||||
- `ui/`: web UI
|
- `ui/`: web UI
|
||||||
- `api/`: API service (Python)
|
- `api/`: API service (Python)
|
||||||
- `docker-compose.yml`: local stack and self-hosted deployment
|
- `docker-compose.yml`: local stack and self-hosted deployment
|
||||||
- `nginx/`: reverse proxy / TLS termination for local HTTPS
|
- `nginx/`: optional reverse proxy / TLS termination (used by Docker Compose)
|
||||||
|
|
||||||
## Quick start
|
## Quick start
|
||||||
|
|
||||||
@@ -63,6 +64,7 @@ docker compose up --build
|
|||||||
|
|
||||||
Open `https://localhost` for the UI (HTTP redirects to HTTPS).
|
Open `https://localhost` for the UI (HTTP redirects to HTTPS).
|
||||||
In the default Compose configuration, only `nginx` is published to the host. The API, Postgres, and wallet-rpc services are reachable only inside the Docker network.
|
In the default Compose configuration, only `nginx` is published to the host. The API, Postgres, and wallet-rpc services are reachable only inside the Docker network.
|
||||||
|
If you prefer not to run `nginx`, you can publish `ui` and `api` ports directly instead (you will also need to serve `qr/` at `/qr/` on your site URL).
|
||||||
|
|
||||||
## Self-hosted deployment (Docker Compose)
|
## Self-hosted deployment (Docker Compose)
|
||||||
|
|
||||||
@@ -127,6 +129,130 @@ To enable donations:
|
|||||||
|
|
||||||
The UI uses the same flag (via Compose), so `/donate` stays unavailable unless donations are explicitly enabled.
|
The UI uses the same flag (via Compose), so `/donate` stays unavailable unless donations are explicitly enabled.
|
||||||
|
|
||||||
|
## Self-hosted deployment (no Docker)
|
||||||
|
|
||||||
|
This section describes running the services directly on a host (or VMs) without Docker.
|
||||||
|
|
||||||
|
You will run:
|
||||||
|
- Postgres (external service)
|
||||||
|
- API (`gunicorn` / `uvicorn`)
|
||||||
|
- Reconciler worker (a separate process)
|
||||||
|
- UI (Next.js)
|
||||||
|
- A reverse proxy is optional, but strongly recommended for TLS, serving `/qr/`, and providing a single origin for UI + API.
|
||||||
|
|
||||||
|
### 1. Install prerequisites
|
||||||
|
|
||||||
|
- Postgres 16+
|
||||||
|
- Python 3.12+
|
||||||
|
- Node.js 20+ (for the UI)
|
||||||
|
- A Monero daemon endpoint (`MONERO_DAEMON_URL`) and at least one `monero-wallet-rpc` instance reachable by the API
|
||||||
|
|
||||||
|
### 2. Configure environment variables
|
||||||
|
|
||||||
|
Start from `.env.example` and adjust for your host. For non-Docker deployments you will typically set:
|
||||||
|
- `DATABASE_URL=postgresql://...@127.0.0.1:5432/...`
|
||||||
|
- `QR_STORAGE_DIR` to a persistent directory on disk (for example `/var/lib/xmrcheckout/qr`)
|
||||||
|
- `SITE_URL` to your public URL (for example `https://example.com`)
|
||||||
|
- `API_BASE_URL` for the UI:
|
||||||
|
- If using a reverse proxy that routes `/api/` to the API on the same origin, set `API_BASE_URL=https://example.com`
|
||||||
|
- If not using a reverse proxy, set `API_BASE_URL=http://127.0.0.1:8000` (see the notes in step 6)
|
||||||
|
|
||||||
|
If you need a new `API_KEY_ENCRYPTION_KEY` value:
|
||||||
|
|
||||||
|
```
|
||||||
|
python -c 'from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())'
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Create the Postgres database
|
||||||
|
|
||||||
|
Create a database and user matching your `DATABASE_URL`. On first startup, the API will create tables automatically.
|
||||||
|
|
||||||
|
### 4. Run the API
|
||||||
|
|
||||||
|
```
|
||||||
|
python -m venv api/.venv
|
||||||
|
api/.venv/bin/pip install -r api/requirements.txt
|
||||||
|
|
||||||
|
# Export env vars (or use your process manager to load them)
|
||||||
|
set -a
|
||||||
|
source .env
|
||||||
|
set +a
|
||||||
|
|
||||||
|
api/.venv/bin/gunicorn app.main:app -k uvicorn.workers.UvicornWorker -b 127.0.0.1:8000 -w "${GUNICORN_WORKERS:-2}" --chdir api
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Run the reconciler worker
|
||||||
|
|
||||||
|
Run this as a separate long-running process (same environment variables as the API):
|
||||||
|
|
||||||
|
```
|
||||||
|
set -a
|
||||||
|
source .env
|
||||||
|
set +a
|
||||||
|
|
||||||
|
api/.venv/bin/python -m app.reconciler
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. Build and run the UI
|
||||||
|
|
||||||
|
```
|
||||||
|
cd ui
|
||||||
|
npm ci
|
||||||
|
|
||||||
|
# Optional but recommended to keep these explicit in non-Docker deployments
|
||||||
|
export API_BASE_URL="${API_BASE_URL:-http://127.0.0.1:8000}"
|
||||||
|
export NEXT_PUBLIC_SITE_URL="${SITE_URL:-http://127.0.0.1:3000}"
|
||||||
|
export NEXT_PUBLIC_DONATIONS_ENABLED="${DONATIONS_ENABLED:-false}"
|
||||||
|
|
||||||
|
npm run build
|
||||||
|
npm run start -- -p 3000 -H 127.0.0.1
|
||||||
|
```
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
- The UI makes some in-browser requests to `/api/...` on the same origin. In production, prefer a reverse proxy that serves the UI and forwards `/api/` to the API.
|
||||||
|
- The QR PNGs are written to `QR_STORAGE_DIR` and must be reachable at `https://<your-site>/qr/<invoice_id>.png`.
|
||||||
|
|
||||||
|
### Optional: reverse proxy (Nginx)
|
||||||
|
|
||||||
|
Nginx is optional. Any reverse proxy that can:
|
||||||
|
- route `/api/` to the API,
|
||||||
|
- route `/` to the UI,
|
||||||
|
- and serve the QR directory at `/qr/`
|
||||||
|
|
||||||
|
is fine.
|
||||||
|
|
||||||
|
Example (adjust `server_name`, TLS, and paths to match your host):
|
||||||
|
|
||||||
|
```
|
||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
server_name example.com;
|
||||||
|
|
||||||
|
# ssl_certificate ...;
|
||||||
|
# ssl_certificate_key ...;
|
||||||
|
|
||||||
|
location /api/ {
|
||||||
|
proxy_pass http://127.0.0.1:8000/api/;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /qr/ {
|
||||||
|
alias /var/lib/xmrcheckout/qr/;
|
||||||
|
add_header Cache-Control "public, max-age=31536000, immutable";
|
||||||
|
try_files $uri =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://127.0.0.1:3000/;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Development (API, Python)
|
## Development (API, Python)
|
||||||
|
|
||||||
1. Set environment variables (see `api/.env.example`):
|
1. Set environment variables (see `api/.env.example`):
|
||||||
@@ -147,7 +273,8 @@ pip install -r api/requirements.txt
|
|||||||
3. Start the API:
|
3. Start the API:
|
||||||
|
|
||||||
```
|
```
|
||||||
uvicorn api.app.main:app --reload
|
cd api
|
||||||
|
uvicorn app.main:app --reload
|
||||||
```
|
```
|
||||||
|
|
||||||
The API listens on `http://127.0.0.1:8000`.
|
The API listens on `http://127.0.0.1:8000`.
|
||||||
|
|||||||
Reference in New Issue
Block a user