ThinkRoot

bine ați navigat pe insula mea de pe internet

Am făcut accesibile toate serviciile self-hosted prin Tailscale

În articolul anterior am documentat cum am mutat serviciile self-hosted de pe Linux Mint pe un Intel NUC cu Ubuntu Server. La final, Vaultwarden mergea deja prin HTTPS via Tailscale și Caddy, dar celelalte șapte servicii - FreshRSS, Wallabag, Linkding, Booktracker, Paperless-ngx, Domain Locker și Scrutiny - rămăseseră accesibile doar în rețeaua locală.

Voiam să le accesez de pe orice dispozitiv, fără să fiu legat de rețeaua de acasă. Așa că am făcut următorii pași:

Pasul 1 - Crearea unei rețele Docker comune

Caddy ajungea la Vaultwarden prin numele containerului (vaultwarden:80) pentru că erau în aceeași rețea Docker. Celelalte servicii rulau în stacks separate, deci Caddy nu le vedea deloc. Soluția a fost să creez o rețea externă comună:

docker network create caddy-proxy

Apoi am editat fiecare docker-compose.yml să includă rețeaua. De exemplu pentru FreshRSS:

services:
  freshrss:
    ...
    networks:
      - caddy-proxy

networks:
  caddy-proxy:
    external: true

Am făcut același lucru pentru wallabag, linkding, booktracker, paperless, domain-locker și scrutiny, apoi am repornit fiecare stack:

for svc in freshrss wallabag linkding booktracker paperless domain-locker scrutiny; do
  cd /opt/services/$svc && docker compose up -d
done

Pasul 2 - Actualizarea docker-compose.yml al Caddy

Caddy trebuia să fie în ambele rețele și să expună porturile noi. Am editat /opt/services/caddy/docker-compose.yml:

services:
  caddy:
    image: caddy:latest
    container_name: caddy
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "8443:8443"
      - "6543:6543"
      - "9443:9443"
      - "2443:2443"
      - "8019:8019"
      - "3443:3443"
      - "8889:8889"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - ./certs:/certs
      - caddy_data:/data
      - caddy_config:/config
    networks:
      - vaultwarden_default
      - caddy-proxy

volumes:
  caddy_data:
  caddy_config:

networks:
  vaultwarden_default:
    external: true
  caddy-proxy:
    external: true

Câteva observații despre porturi: portul 8010 era deja ocupat de Paperless pe host, iar 8888 de Scrutiny, deci am ales 8019 și 8889 ca să evit conflictele.

Pasul 3 - Configurarea Caddyfile

Certificatul existent de la Tailscale era valabil doar pentru hostname-ul exact thinkserver.tailxxxx.ts.net, fără subdomenii. Soluția a fost să folosesc porturi diferite pentru fiecare serviciu, toate cu același certificat. Am editat /opt/services/caddy/Caddyfile:

thinkserver.tailxxxx.ts.net {
    tls /certs/thinkserver.tailxxxx.ts.net.crt /certs/thinkserver.tailxxxx.ts.net.key
    reverse_proxy vaultwarden:80
}

thinkserver.tailxxxx.ts.net:8443 {
    tls /certs/thinkserver.tailxxxx.ts.net.crt /certs/thinkserver.tailxxxx.ts.net.key
    reverse_proxy freshrss:80
}

thinkserver.tailxxxx.ts.net:6543 {
    tls /certs/thinkserver.tailxxxx.ts.net.crt /certs/thinkserver.tailxxxx.ts.net.key
    reverse_proxy wallabag:80
}

thinkserver.tailxxxx.ts.net:9443 {
    tls /certs/thinkserver.tailxxxx.ts.net.crt /certs/thinkserver.tailxxxx.ts.net.key
    reverse_proxy linkding:9090
}

thinkserver.tailxxxx.ts.net:2443 {
    tls /certs/thinkserver.tailxxxx.ts.net.crt /certs/thinkserver.tailxxxx.ts.net.key
    reverse_proxy booktracker:5000
}

thinkserver.tailxxxx.ts.net:8019 {
    tls /certs/thinkserver.tailxxxx.ts.net.crt /certs/thinkserver.tailxxxx.ts.net.key
    reverse_proxy paperless:8000
}

thinkserver.tailxxxx.ts.net:3443 {
    tls /certs/thinkserver.tailxxxx.ts.net.crt /certs/thinkserver.tailxxxx.ts.net.key
    reverse_proxy domain-locker-app:3000
}

thinkserver.tailxxxx.ts.net:8889 {
    tls /certs/thinkserver.tailxxxx.ts.net.crt /certs/thinkserver.tailxxxx.ts.net.key
    reverse_proxy scrutiny:8080
}

Un detaliu important: în reverse_proxy trebuie folosit numele containerului, nu cel al serviciului din Compose. De exemplu, Domain Locker are containerul domain-locker-app, nu domain-locker. L-am verificat cu:

grep "container_name" /opt/services/*/docker-compose.yml

Porturile din reverse_proxy sunt cele interne ale containerului, nu cele de pe host. Le-am verificat cu:

grep -A3 "ports:" /opt/services/*/docker-compose.yml

Pasul 4 - Pornirea Caddy și reîncărcarea configurației

cd /opt/services/caddy && docker compose up -d
docker exec caddy caddy reload --config /etc/caddy/Caddyfile

Pasul 5 - Wallabag: actualizarea domeniului

Wallabag generează URL-uri absolute pentru CSS și JavaScript pe baza variabilei SYMFONY__ENV__DOMAIN_NAME. Era setată pe IP-ul local vechi, ceea ce făcea ca grafica să nu se încarce când accesam din afara rețelei. Am actualizat în /opt/services/wallabag/docker-compose.yml:

environment:
  - SYMFONY__ENV__DOMAIN_NAME=https://thinkserver.tailxxxx.ts.net:6543

Apoi:

cd /opt/services/wallabag && docker compose up -d

Rezultatul final

Toate serviciile sunt acum accesibile prin HTTPS de pe orice dispozitiv cu Tailscale conectat.

⬅ The one before
Prietenia și bunătatea

Up next ➡
Românul și confidențialitatea: „Nu am nimic de ascuns"