121 lines
4.7 KiB
Markdown
121 lines
4.7 KiB
Markdown
# Nginx Proxy Manager migration
|
|
|
|
RustProxy ships `scripts/migrate_npm.py` for a one-time, dry-run-first migration of
|
|
Nginx Proxy Manager (NPM) proxy hosts from its SQLite database.
|
|
|
|
The tool reads NPM only. It does not modify the NPM database and it never imports
|
|
Let's Encrypt/private-key material. It logs in to the RustProxy administration API,
|
|
reads the current revision, merges generated vhosts into the existing configuration,
|
|
and writes only when `--apply` is supplied.
|
|
|
|
`migrate_npm.py` is the CLI entry point and requires the sibling modules
|
|
`scripts/migrate_npm_core.py` and `scripts/migrate_npm_api.py`. They use only the
|
|
Python standard library, so no `pip` packages are required. If the migrator is copied
|
|
or mounted outside the RustProxy source tree, keep all three files in the same directory.
|
|
|
|
## What is migrated
|
|
|
|
For each NPM `proxy_host` row:
|
|
|
|
- `domain_names` -> RustProxy vhost hostnames, including leading `*.` wildcards;
|
|
- `forward_scheme`, `forward_host`, `forward_port` -> one RustProxy backend;
|
|
- `allow_websocket_upgrade` -> vhost WebSocket policy;
|
|
- `enabled` -> vhost enabled state;
|
|
- `http2_support` -> vhost HTTP/2 policy;
|
|
- NPM hosts with a certificate/forced SSL -> RustProxy TLS listener. Certificate
|
|
files are not copied: the application-managed RustProxy default certificate is
|
|
used unless `--certificate-id` names an existing RustProxy inventory certificate;
|
|
- `ssl_forced` -> RustProxy `force_ssl=true`. When HTTP and HTTPS listeners exist,
|
|
both are attached so cleartext requests can receive RustProxy's `308` redirect to
|
|
HTTPS. If no TLS listener exists, an SSL-forced NPM host is skipped instead of being
|
|
imported with weaker semantics.
|
|
|
|
Migrated backends use `allow_private=true` because NPM commonly proxies to LAN or
|
|
container origins. The migration tool follows RustProxy 0.22.1 and imports backend `tls_verify=false` unless you later enable verification explicitly.
|
|
Use `--npm-compatible-backend-tls` when an NPM HTTPS origin depends on
|
|
the common Nginx behavior of not verifying the upstream certificate; review that
|
|
exception after migration.
|
|
|
|
The following are reported for manual review rather than guessed: NPM access lists,
|
|
advanced Nginx snippets, custom locations, NPM cache settings and `block_exploits`.
|
|
Existing RustProxy hostname ownership is never silently replaced; conflicting NPM
|
|
rows are skipped and shown in the report.
|
|
|
|
## SQLite location
|
|
|
|
The standard NPM SQLite path inside the container is `/data/database.sqlite`. On a
|
|
Docker host with a bind mount, pass the corresponding host path. For a named volume,
|
|
`docker volume inspect` shows its mountpoint.
|
|
|
|
Read the live mounted database rather than copying only `database.sqlite` from a
|
|
running WAL-mode instance; copying without its WAL file can omit recent changes.
|
|
|
|
## Dry run
|
|
|
|
Set the password in the environment or omit it and use the interactive prompt:
|
|
|
|
```bash
|
|
export RUSTPROXY_USERNAME=admin
|
|
export RUSTPROXY_PASSWORD='...'
|
|
|
|
python3 scripts/migrate_npm.py \
|
|
--database /path/to/npm/data/database.sqlite \
|
|
--rustproxy https://rustproxy.example.net:9090
|
|
```
|
|
|
|
The default run is read-only. It creates `npm-migration-plan.json` with mode `0600`
|
|
and prints every imported/skipped NPM row plus manual-review warnings.
|
|
|
|
If the administration panel intentionally uses the application self-signed
|
|
certificate and the script connects directly to it, add:
|
|
|
|
```bash
|
|
--insecure-admin-tls
|
|
```
|
|
|
|
Prefer `--ca-file /path/to/ca.pem` or a hostname with a trusted certificate where
|
|
available.
|
|
|
|
By default the first enabled HTTP listener and first enabled TLS listener are used.
|
|
For `ssl_forced` hosts both are selected when available. `--force-https` applies the
|
|
same Force SSL policy to every imported host. Select explicit listener IDs when needed:
|
|
|
|
```bash
|
|
--http-listener public-http --https-listener public-https
|
|
```
|
|
|
|
## Apply
|
|
|
|
After reviewing `npm-migration-plan.json`:
|
|
|
|
```bash
|
|
python3 scripts/migrate_npm.py \
|
|
--database /path/to/npm/data/database.sqlite \
|
|
--rustproxy https://rustproxy.example.net:9090 \
|
|
--apply
|
|
```
|
|
|
|
The write uses the revision returned by `GET /api/config`; a concurrent RustProxy
|
|
configuration change causes the API compare-and-swap to fail rather than overwrite a
|
|
newer revision.
|
|
|
|
## Running from a helper container
|
|
|
|
If the Docker host does not have Python 3, mount the NPM data read-only and mount the
|
|
RustProxy source/script into a temporary Python container. For example, from the
|
|
RustProxy directory:
|
|
|
|
```bash
|
|
docker run --rm -it \
|
|
--network host \
|
|
-v /path/to/npm/data:/npm:ro \
|
|
-v "$PWD/scripts:/rustproxy-scripts:ro" \
|
|
python:3.13-alpine \
|
|
python /rustproxy-scripts/migrate_npm.py \
|
|
--database /npm/database.sqlite \
|
|
--rustproxy https://127.0.0.1:9090 \
|
|
--insecure-admin-tls
|
|
```
|
|
|
|
Use `--apply` only after the dry-run plan is reviewed.
|