6.2 KiB
6.2 KiB
Joplin Server
Description
This page documents the current Joplin Server state on the Hetzner VPS.
Joplin Server is running on the VPS and is reachable through Nginx Proxy Manager when requests resolve to the VPS IP.
Current configuration
- Compose path:
/home/dockeruser/docker/joplin-server - Files:
/home/dockeruser/docker/joplin-server/docker-compose.yml/home/dockeruser/docker/joplin-server/.env/home/dockeruser/docker/joplin-server/README.md
- Current runtime state: running
docker compose psin/home/dockeruser/docker/joplin-servershows:joplin-db: healthyjoplin-server: up, bound to127.0.0.1:22300
- Intended public URL:
https://joplin.okit.pl
Current DNS issue:
joplin.okit.plcurrently returnsCNAME okit.pl, but no valid A or AAAA answer.- Let's Encrypt failed with:
no valid A records found for joplin.okit.pl; no valid AAAA records found for joplin.okit.pl. - DNS needs to be fixed before normal public HTTPS works.
Fixes applied on 2026-04-15:
- Recreated the Joplin compose stack so
joplin-dbused the current Postgres 18 mount layout. - Confirmed the Joplin
.envpassword is no longer the placeholder. - Joplin app started successfully and auto-migrated the database.
- Updated Nginx Proxy Manager's
proxy_hostdatabase row forjoplin.okit.plto forward tohttp://127.0.0.1:22300, with websockets and block-exploits enabled. - Manually updated active NPM config at
/home/dockeruser/docker/npm/data/nginx/proxy_host/1.confto use127.0.0.1:22300, because this NPM instance did not regenerate the config from SQLite on restart. - Reloaded nginx successfully.
Successful tests on 2026-04-15:
curl -sS http://127.0.0.1:22300/api/ping -H 'Host: joplin.okit.pl'
# {"status":"ok","message":"Joplin Server is running"}
curl -sS http://127.0.0.1/api/ping -H 'Host: joplin.okit.pl'
# {"status":"ok","message":"Joplin Server is running"}
curl -sS --resolve joplin.okit.pl:80:135.181.153.108 http://joplin.okit.pl/api/ping
# {"status":"ok","message":"Joplin Server is running"}
Laptop-side diagnostics on 2026-04-15:
- Direct test to Joplin over Tailscale:
- Command:
curl -v --connect-timeout 5 http://100.95.58.48:22300 - Result: connection refused.
- Observed source address:
100.121.168.72.
- Command:
- TCP test to SSH over Tailscale:
- Command:
nc -vz 100.95.58.48 22 - Result: connection succeeded.
- Command:
- TCP test to Joplin over Tailscale:
- Command:
nc -vz 100.95.58.48 22300 - Result: connection refused.
- Command:
- Classical SSH test:
- Command:
ssh -o BatchMode=yes -o ConnectTimeout=5 dockeruser@100.95.58.48 true - Result: local SSH client refused to run because
/etc/ssh/ssh_config.d/20-systemd-ssh-proxy.confhas bad owner or permissions.
- Command:
- Classical SSH test with global config bypassed:
- Command:
ssh -F /dev/null -o BatchMode=yes -o ConnectTimeout=5 dockeruser@100.95.58.48 true - Result:
Permission denied (publickey,password).
- Command:
- Tailscale SSH wrapper test:
- Command:
tailscale ssh dockeruser@100.95.58.48 true - Result: host key verification failed because no ED25519 host key is known for
ubuntu-4gb-hel1-1.tailedf7b1.ts.net.
- Command:
- SSH tunnel was not established from the laptop during this test because SSH authentication or host-key verification was not completed.
Known facts
Joplin Compose design:
appimage: joplin/server:latestcontainer_name: joplin-serverrestart: unless-stoppedenv_file: .env- Binds only to localhost:
127.0.0.1:22300:22300
- Depends on
dbwith conditionservice_healthy - Network:
joplin-net
dbimage: postgres:18container_name: joplin-dbrestart: unless-stopped- No exposed ports
- Network:
joplin-net - Volume:
postgres_data:/var/lib/postgresql
- Healthcheck:
pg_isreadyusingPOSTGRES_USERandPOSTGRES_DB
- Named volume:
joplin_postgres_data
- Named network:
joplin-net
Joplin .env:
POSTGRES_PASSWORD=<set on VPS; not placeholder>
POSTGRES_USER=joplin
POSTGRES_DB=joplin
APP_PORT=22300
APP_BASE_URL=https://joplin.okit.pl
DB_CLIENT=pg
POSTGRES_HOST=db
POSTGRES_PORT=5432
Important notes from handoff:
POSTGRES_PASSWORDhas been changed from the original placeholder.- Joplin is intentionally localhost-only.
- External access must go through Nginx Proxy Manager.
- Because Nginx Proxy Manager uses host networking, Nginx Proxy Manager should forward to
127.0.0.1:22300. - PostgreSQL is internal-only and should not be exposed publicly.
Required Nginx Proxy Manager proxy host for Joplin:
- Domain Names:
joplin.okit.pl - Scheme:
http - Forward Hostname / IP:
127.0.0.1 - Forward Port:
22300 - Websockets Support: enabled
- Block Common Exploits: enabled
- SSL:
- Request Let's Encrypt certificate
- Force SSL enabled
- HTTP/2 enabled
DNS plan from handoff:
- Create A record:
joplin.okit.pl -> 135.181.153.108
- Optional AAAA record:
joplin.okit.pl -> 2a01:4f9:c014:98f0::1
- For normal Let's Encrypt through Nginx Proxy Manager, ports
80and443must reach this VPS publicly. - Public DNS should not point to the Tailscale IP if using standard Let's Encrypt HTTP validation.
Commands provided in handoff to start Joplin:
cd /home/dockeruser/docker/joplin-server
nano .env
# replace POSTGRES_PASSWORD
docker compose up -d
docker compose ps
docker compose logs -f app
Local tests on VPS after Joplin start:
curl -I http://127.0.0.1:22300
curl -I http://127.0.0.1:81
curl -I http://127.0.0.1:80
Public tests after DNS and Nginx Proxy Manager config:
dig joplin.okit.pl
curl -I https://joplin.okit.pl
Unknown / needs clarification
- Whether Nginx Proxy Manager will preserve the manual generated-conf fix after future UI edits/restarts. The SQLite row is correct, but the active generated config did not update automatically during this fix.
- Whether
joplin.okit.plDNS has been created or fixed. - Whether the optional AAAA record is intended.
- Whether Let's Encrypt certificate issuance has succeeded.
- Whether the laptop has a valid SSH key or password for
dockeruser@100.95.58.48. - Whether the Tailscale SSH host key for
ubuntu-4gb-hel1-1.tailedf7b1.ts.netshould be accepted on the laptop.