From 52af4904da7b5aeebe2a0023432483197c70112a Mon Sep 17 00:00:00 2001 From: mk Date: Wed, 11 Mar 2026 22:18:38 -0300 Subject: [PATCH] adding untested changes and new dockers --- .../jellyfin}/docker-compose.yml | 0 {navidrome => media/navidrome}/README.md | 0 .../navidrome}/data/navidrome.toml | 0 .../navidrome}/docker-compose.yml | 0 {nextcloud => media/nextcloud}/.env.example | 2 +- .../nextcloud}/docker-compose.yml | 0 {mastodon => social/mastodon}/.env.example | 2 +- .../mastodon}/docker-compose.yml | 0 social/matrix-discord-bridge/.env.example | 5 + .../matrix-discord-bridge/docker-compose.yml | 37 ++++ social/matrix/.env.example | 12 + social/matrix/README.md | 1 + social/matrix/docker-compose.yml | 66 ++++++ social/matrix/homeserver.yml | 150 +++++++++++++ social/matrix/livekit/livekit.yaml | 9 + social/matrix/lk-jwt-proxy/nginx.conf | 19 ++ streaming/.env.example | 2 +- {duplicati => tools/duplicati}/.env.example | 2 +- {duplicati => tools/duplicati}/README.md | 0 .../duplicati}/docker-compose.yml | 0 {gitea => tools/gitea}/README.md | 0 .../gitea}/data/gitea/conf/app.ini | 0 {gitea => tools/gitea}/docker-compose.yml | 0 .../vaultwarden}/.env.example | 0 {vaultwarden => tools/vaultwarden}/README.md | 0 .../vaultwarden}/docker-compose.yml | 0 tools/wireguard/README.md | 175 +++++++++++++++ tools/wireguard/docker-compose.yml | 46 ++++ tools/wireguard/traefik/dynamic.yml | 97 ++++++++ tools/wireguard/traefik/traefik.yml | 45 ++++ tools/wireguard/vps/ports.sh | 208 ++++++++++++++++++ tools/wireguard/vps/setup.sh | 57 +++++ tools/wireguard/vps/wg0.conf | 8 + tools/wireguard/wireguard-config/wg0.conf | 10 + 34 files changed, 949 insertions(+), 4 deletions(-) rename {jellyfin => media/jellyfin}/docker-compose.yml (100%) rename {navidrome => media/navidrome}/README.md (100%) rename {navidrome => media/navidrome}/data/navidrome.toml (100%) rename {navidrome => media/navidrome}/docker-compose.yml (100%) rename {nextcloud => media/nextcloud}/.env.example (80%) rename {nextcloud => media/nextcloud}/docker-compose.yml (100%) rename {mastodon => social/mastodon}/.env.example (95%) rename {mastodon => social/mastodon}/docker-compose.yml (100%) create mode 100644 social/matrix-discord-bridge/.env.example create mode 100644 social/matrix-discord-bridge/docker-compose.yml create mode 100644 social/matrix/.env.example create mode 100644 social/matrix/README.md create mode 100644 social/matrix/docker-compose.yml create mode 100644 social/matrix/homeserver.yml create mode 100644 social/matrix/livekit/livekit.yaml create mode 100644 social/matrix/lk-jwt-proxy/nginx.conf rename {duplicati => tools/duplicati}/.env.example (81%) rename {duplicati => tools/duplicati}/README.md (100%) rename {duplicati => tools/duplicati}/docker-compose.yml (100%) rename {gitea => tools/gitea}/README.md (100%) rename {gitea => tools/gitea}/data/gitea/conf/app.ini (100%) rename {gitea => tools/gitea}/docker-compose.yml (100%) rename {vaultwarden => tools/vaultwarden}/.env.example (100%) rename {vaultwarden => tools/vaultwarden}/README.md (100%) rename {vaultwarden => tools/vaultwarden}/docker-compose.yml (100%) create mode 100644 tools/wireguard/README.md create mode 100644 tools/wireguard/docker-compose.yml create mode 100644 tools/wireguard/traefik/dynamic.yml create mode 100644 tools/wireguard/traefik/traefik.yml create mode 100644 tools/wireguard/vps/ports.sh create mode 100644 tools/wireguard/vps/setup.sh create mode 100644 tools/wireguard/vps/wg0.conf create mode 100644 tools/wireguard/wireguard-config/wg0.conf diff --git a/jellyfin/docker-compose.yml b/media/jellyfin/docker-compose.yml similarity index 100% rename from jellyfin/docker-compose.yml rename to media/jellyfin/docker-compose.yml diff --git a/navidrome/README.md b/media/navidrome/README.md similarity index 100% rename from navidrome/README.md rename to media/navidrome/README.md diff --git a/navidrome/data/navidrome.toml b/media/navidrome/data/navidrome.toml similarity index 100% rename from navidrome/data/navidrome.toml rename to media/navidrome/data/navidrome.toml diff --git a/navidrome/docker-compose.yml b/media/navidrome/docker-compose.yml similarity index 100% rename from navidrome/docker-compose.yml rename to media/navidrome/docker-compose.yml diff --git a/nextcloud/.env.example b/media/nextcloud/.env.example similarity index 80% rename from nextcloud/.env.example rename to media/nextcloud/.env.example index 8b43fdf..1efe335 100644 --- a/nextcloud/.env.example +++ b/media/nextcloud/.env.example @@ -1,6 +1,6 @@ PUID=1000 PGID=1001 -TZ=America/Sao_Paulo +TZ=America/Chicago PORT=8443 MYSQL_ROOT_PASSWORD=changeme DATABASE_PASSWORD=changeme diff --git a/nextcloud/docker-compose.yml b/media/nextcloud/docker-compose.yml similarity index 100% rename from nextcloud/docker-compose.yml rename to media/nextcloud/docker-compose.yml diff --git a/mastodon/.env.example b/social/mastodon/.env.example similarity index 95% rename from mastodon/.env.example rename to social/mastodon/.env.example index e043a90..8657ed0 100644 --- a/mastodon/.env.example +++ b/social/mastodon/.env.example @@ -1,6 +1,6 @@ PUID=1000 PGID=1001 -TZ=America/Sao_Paulo +TZ=America/Chicago # Domain LOCAL_DOMAIN=yourdomainhere diff --git a/mastodon/docker-compose.yml b/social/mastodon/docker-compose.yml similarity index 100% rename from mastodon/docker-compose.yml rename to social/mastodon/docker-compose.yml diff --git a/social/matrix-discord-bridge/.env.example b/social/matrix-discord-bridge/.env.example new file mode 100644 index 0000000..a4498ac --- /dev/null +++ b/social/matrix-discord-bridge/.env.example @@ -0,0 +1,5 @@ +POSTGRES_PASSWORD=changeme + +# Optional really +POSTGRES_USER=mautrix-discord +POSTGRES_DB=mautrix-discord diff --git a/social/matrix-discord-bridge/docker-compose.yml b/social/matrix-discord-bridge/docker-compose.yml new file mode 100644 index 0000000..754ace4 --- /dev/null +++ b/social/matrix-discord-bridge/docker-compose.yml @@ -0,0 +1,37 @@ +version: "3.7" + +services: + mautrix-discord: + container_name: mautrix-discord + image: dock.mau.dev/mautrix/discord:latest + restart: unless-stopped + volumes: + - ./data:/data + + ports: + - "29334:29334" + + networks: + synapse_default: + + mautrix-discord-db: + image: docker.io/postgres:15-alpine + container_name: mautrix-discord-db + restart: always + environment: + - POSTGRES_USER=${POSTGRES_USER} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} + - POSTGRES_DB=${POSTGRES_DB} + # ensure the database gets created correctly + # https://github.com/matrix-org/synapse/blob/master/docs/postgres.md#set-up-database + - POSTGRES_INITDB_ARGS=--encoding=UTF-8 --lc-collate=C --lc-ctype=C + volumes: + # You may either store all the files in a local folder + - ./db:/var/lib/postgresql/data + ports: + - 5432:5432 + networks: + synapse_default: + +networks: + synapse_default: diff --git a/social/matrix/.env.example b/social/matrix/.env.example new file mode 100644 index 0000000..e31daf9 --- /dev/null +++ b/social/matrix/.env.example @@ -0,0 +1,12 @@ +# Synapse homeserver domain (cannot be changed after federation starts) +SYNAPSE_SERVER_NAME=matrix.example.com + +TZ=UTC + +# LiveKit JWT service credentials +# Generate a key/secret pair: https://docs.livekit.io/home/self-hosting/deployment/ +LIVEKIT_KEY=changeme +LIVEKIT_SECRET=changeme + +# Optional: override if livekit is not on localhost +# LIVEKIT_URL=ws://localhost:7880 diff --git a/social/matrix/README.md b/social/matrix/README.md new file mode 100644 index 0000000..7e872b3 --- /dev/null +++ b/social/matrix/README.md @@ -0,0 +1 @@ +Update livekit.yaml and nginx.conf with homeserver's name diff --git a/social/matrix/docker-compose.yml b/social/matrix/docker-compose.yml new file mode 100644 index 0000000..c573bc4 --- /dev/null +++ b/social/matrix/docker-compose.yml @@ -0,0 +1,66 @@ +services: + synapse: + image: matrixdotorg/synapse:latest + container_name: synapse + restart: unless-stopped + environment: + SYNAPSE_SERVER_NAME: ${SYNAPSE_SERVER_NAME} + SYNAPSE_CONFIG_PATH: /data/homeserver.yaml + UID: "991" + GID: "991" + TZ: ${TZ:-UTC} + volumes: + - ./synapse:/data + ports: + # Client & federation API (put a reverse proxy in front for TLS) + - "8008:8008" + healthcheck: + test: + [ + "CMD-SHELL", + "curl -fSs http://localhost:8008/health || exit 1", + ] + interval: 15s + timeout: 5s + retries: 3 + start_period: 30s + + livekit: + image: livekit/livekit-server:latest + container_name: livekit + restart: unless-stopped + command: --config /etc/livekit.yaml + volumes: + - ./livekit/:/etc/ + network_mode: "container:wireguard" + + lk-jwt: + image: ghcr.io/element-hq/lk-jwt-service:latest + container_name: lk-jwt + restart: unless-stopped + environment: + LIVEKIT_URL: ${LIVEKIT_URL:-ws://localhost:7880} + LIVEKIT_KEY: ${LIVEKIT_KEY} + LIVEKIT_SECRET: ${LIVEKIT_SECRET} + LIVEKIT_JWT_BIND: ":8090" + LIVEKIT_INSECURE_SKIP_VERIFY_TLS: "true" + network_mode: "container:wireguard" + depends_on: + - livekit + + lk-jwt-proxy: + image: nginx:alpine + container_name: lk-jwt-proxy + restart: unless-stopped + volumes: + - ./lk-jwt-proxy/:/etc/nginx/:ro + network_mode: "container:wireguard" + depends_on: + - lk-jwt + + synapse-admin: + image: awesometechnologies/synapse-admin:latest + container_name: synapse-admin + restart: unless-stopped + ports: + - "8087:80" diff --git a/social/matrix/homeserver.yml b/social/matrix/homeserver.yml new file mode 100644 index 0000000..a26bd7e --- /dev/null +++ b/social/matrix/homeserver.yml @@ -0,0 +1,150 @@ +# Configuration file for Synapse. +# Config by Mosskoi +# This configuration intends on creating a private experience for matrix +# By default it disallows communication with federated services and other servers +# But by configuring a whitelist you can adds more servers to your network +# Make sure these other servers have the same whitelist server as you +# Matrix does not disallow + +# * Server +server_name: "matrix.example.com" +public_baseurl: https://matrix.example.com/ + +serve_server_wellknown: true +extra_well_known_client_content: + org.matrix.msc4143.rtc_foci: + - type: livekit + livekit_service_url: https://livekit.example.com + +# Currently unused +#ip_range_blacklist: +#- 127.0.0.0/8 +#ip_range_whitelist: +#- 192.168.1.1 + +listeners: + - port: 8008 + resources: + - compress: false + names: + - client + - federation + tls: false + type: http + x_forwarded: true + +# * Homeserver blocking + +require_membership_for_aliases: false +max_avatar_size: 5M +allowed_avatar_mimetypes: + - image/png + - image/jpeg + - image/webp + - image/gif + +user_ips_max_age: 90d + +# * TLS +# Currently not used +# federation_certificate_verification_whitelist: +#- lon.example.com + +# * Federation +# Private federation system +federation_domain_whitelist: + - matrix.example.com +federation_metrics_domains: + - matrix.example.com + +allow_profile_lookup_over_federation: false +allow_device_name_lookup_over_federation: false + +federation: + client_timeout: 60s + max_short_retry_delay: 7s + max_long_retry_delay: 100s + max_short_retries: 3 + max_long_retries: 7 + destination_min_retry_interval: 10m + destination_retry_multiplier: 2 + destination_max_retry_interval: 12h + +database: + name: sqlite3 + args: + database: /data/homeserver.db +log_config: "/data/matrix.example.com.log.config" + +# * Logging +# * Rate limiting +rc_registration: + per_second: 0.1 + burst_count: 2.0 + +# * Media Store +media_store_path: /data/media_store +max_pending_media_uploads: 10 +#url_preview_enabled: true Must explicit blacklist +# * Captcha +# * TURN +matrix_rtc: + transports: + - type: livekit + livekit_service_url: https://livekit.example.com + +# * Registration +enable_registration: true # Must be enabled for token registrations to work +enable_registration_without_verification: false +disable_msisdn_registration: true +enable_3pid_lookup: false +registration_requires_token: true +registration_shared_secret: REGISTRATION_SECRET + +enable_set_displayname: true +enable_set_avatar_url: true +enable_3pids_changes: true + +allow_guest_access: false + +autocreate_auto_join_rooms: false +autocreate_auto_join_rooms_federated: false +auto_join_rooms_for_guests: false + +# * User session management +login_via_existing_session: + enabled: true + require_ui_auth: false + token_timeout: 5m + +# * API Configuration +# +macaroon_secret_key: "MACAROON_SECRET" +form_secret: "FROM_SECRET" +signing_key_path: "/data/matrix.example.com.signing.key" + +# * Rooms +user_directory: + enabled: false + search_all_users: false + prefer_local_users: true + exclude_remote_users: false + show_locked_users: false + +enable_room_list_search: true + +# Guest sign-in + +pid_file: /data/homeserver.pid + +# Signing and secrets +report_stats: false +trusted_key_servers: [] +# - server_name: "matrix.example.com" + +experimental_features: + msc4143_enabled: true +# vim:ft=yaml + +app_service_config_files: + - /data/registration.yaml diff --git a/social/matrix/livekit/livekit.yaml b/social/matrix/livekit/livekit.yaml new file mode 100644 index 0000000..074e5a2 --- /dev/null +++ b/social/matrix/livekit/livekit.yaml @@ -0,0 +1,9 @@ +port: 7880 +rtc: + tcp_port: 7881 + port_range_start: 50100 + enabled: true + domain: livekit.example.com + tls_port: 5349 + udp_port: 3478 + external_tls: true diff --git a/social/matrix/lk-jwt-proxy/nginx.conf b/social/matrix/lk-jwt-proxy/nginx.conf new file mode 100644 index 0000000..c61daf1 --- /dev/null +++ b/social/matrix/lk-jwt-proxy/nginx.conf @@ -0,0 +1,19 @@ +events { + worker_connections 64; +} + +http { + server { + listen 8091; + + location / { + proxy_pass http://localhost:8090; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + + sub_filter_types application/json; + sub_filter 'ws://localhost:7880' 'wss://livekit.example.com'; + sub_filter_once off; + } + } +} diff --git a/streaming/.env.example b/streaming/.env.example index fa76606..902bb2b 100644 --- a/streaming/.env.example +++ b/streaming/.env.example @@ -1,3 +1,3 @@ RS_USERNAME=admin RS_PASSWORD=changeme -TZ=America/Sao_Paulo +TZ=America/Chicago diff --git a/duplicati/.env.example b/tools/duplicati/.env.example similarity index 81% rename from duplicati/.env.example rename to tools/duplicati/.env.example index 4aff3b0..44599b3 100644 --- a/duplicati/.env.example +++ b/tools/duplicati/.env.example @@ -1,6 +1,6 @@ PUID=1000 PGID=1001 -TZ=America/Sao_Paulo +TZ=America/Chicago SETTINGS_ENCRYPTION_KEY=changeme SOURCE_PATH=./source BACKUP_PATH=./backup diff --git a/duplicati/README.md b/tools/duplicati/README.md similarity index 100% rename from duplicati/README.md rename to tools/duplicati/README.md diff --git a/duplicati/docker-compose.yml b/tools/duplicati/docker-compose.yml similarity index 100% rename from duplicati/docker-compose.yml rename to tools/duplicati/docker-compose.yml diff --git a/gitea/README.md b/tools/gitea/README.md similarity index 100% rename from gitea/README.md rename to tools/gitea/README.md diff --git a/gitea/data/gitea/conf/app.ini b/tools/gitea/data/gitea/conf/app.ini similarity index 100% rename from gitea/data/gitea/conf/app.ini rename to tools/gitea/data/gitea/conf/app.ini diff --git a/gitea/docker-compose.yml b/tools/gitea/docker-compose.yml similarity index 100% rename from gitea/docker-compose.yml rename to tools/gitea/docker-compose.yml diff --git a/vaultwarden/.env.example b/tools/vaultwarden/.env.example similarity index 100% rename from vaultwarden/.env.example rename to tools/vaultwarden/.env.example diff --git a/vaultwarden/README.md b/tools/vaultwarden/README.md similarity index 100% rename from vaultwarden/README.md rename to tools/vaultwarden/README.md diff --git a/vaultwarden/docker-compose.yml b/tools/vaultwarden/docker-compose.yml similarity index 100% rename from vaultwarden/docker-compose.yml rename to tools/vaultwarden/docker-compose.yml diff --git a/tools/wireguard/README.md b/tools/wireguard/README.md new file mode 100644 index 0000000..69dd693 --- /dev/null +++ b/tools/wireguard/README.md @@ -0,0 +1,175 @@ +# WireGuard VPN + Traefik Reverse Proxy Setup + +## Architecture + +``` +Internet → VPS → WireGuard tunnel → Home Server → Traefik → Containers +``` + +## Files Structure + +``` +wireguard/ +├── vps/ +│ ├── wg0.conf # WireGuard config for VPS +│ ├── setup.sh # Setup script for VPS +│ └── ports.sh # Iptables update script for new ports +├── home/ +│ ├── docker-compose.yml +│ ├── wireguard-config/ +│ │ └── wg0.conf # WireGuard config for home +│ ├── traefik/ +│ │ ├── traefik.yml # Traefik static config +│ │ └── dynamic.yml # Traefik dynamic config +└── README.md +``` + +--- + +## Step 1: Setup VPS (Debian) + +1. Copy the `vps/` folder to your VPS + +2. Run the setup script: + + ```bash + chmod +x setup.sh + sudo ./setup.sh + ``` + +3. The script will output your VPS keys. Save them: + - **VPS Private Key** → put in `vps/wg0.conf` + - **VPS Public Key** → put in `home/wireguard-config/wg0.conf` + +4. Copy the updated `wg0.conf` to `/etc/wireguard/wg0.conf` + +5. Wait for Step 2 to get the home public key before starting WireGuard + +--- + +## Step 2: Setup Home Server (Arch) + +1. Copy the `home/` folder to your home server + +2. Generate WireGuard keys: + + ```bash + wg genkey | tee privatekey | wg pubkey > publickey + cat privatekey # → put in home/wireguard-config/wg0.conf + cat publickey # → put in vps/wg0.conf on VPS + ``` + +3. Edit `home/wireguard-config/wg0.conf`: + - Replace `HOME_PRIVATE_KEY` with your private key + - Replace `VPS_PUBLIC_KEY` with the VPS public key from Step 1 + +4. Start the containers: + ```bash + docker compose up -d + ``` + +--- + +## Step 3: Finish VPS Setup + +1. On VPS, edit `/etc/wireguard/wg0.conf`: + - Replace `HOME_PUBLIC_KEY` with your home server's public key + +2. Start WireGuard: + + ```bash + sudo systemctl start wg-quick@wg0 + ``` + +3. Test the tunnel: + ```bash + ping 10.0.0.2 + ``` + +--- + +## Step 4: Point Your Domain to VPS + +Create DNS A records pointing to your VPS IP: + +``` +exampledomain.com → VPS_IP +*.exampledomain.com → VPS_IP (wildcard for subdomains) +``` + +--- + +## Step 5: Configure connections to your Containers + +Add Traefik configurations to dynamic.yml, the file comes with a simple example: + +```yaml +routers: + example-app: #Define service name + # Rules define the domain and/or subdomain you want to use + rule: "Host(`exampledomain.com`) || Host(`subdomain.exampledomain.com`)" + entryPoints: + - web # use HTTP + - websecure # use HTTPS + example-app: blog + +services: + example-app: #Service name + loadBalancer: + servers: + - url: "http://example-docker:80" #Docker IP/name and port to have DNS redirect to +``` + +See `dynamic.yml` for a complete example and use it for configuration. + +--- + +## Useful Commands + +### VPS + +```bash +# Check WireGuard status +sudo wg show + +# View iptables rules +sudo iptables -t nat -L -n -v + +# Restart WireGuard +sudo systemctl restart wg-quick@wg0 +``` + +### Home Server + +```bash +# View logs +docker compose logs -f + +# Restart services +docker compose restart + +# Check WireGuard status inside container +docker exec wireguard wg show +``` + +--- + +## Troubleshooting + +### Tunnel not connecting + +- Check both public keys are correct +- Ensure VPS firewall allows UDP 51820 +- Check `PersistentKeepalive` is set (for NAT traversal) + +### Traefik not getting certificates + +- Ensure port 80 is forwarded through VPS +- Check DNS is pointing to VPS IP +- View Traefik logs: `docker compose logs traefik` + +### Traffic not reaching home server + +- Test tunnel: `ping 10.0.0.2` from VPS +- Check iptables: `sudo iptables -t nat -L PREROUTING -n -v` +- Ensure ip_forward is enabled: `cat /proc/sys/net/ipv4/ip_forward` diff --git a/tools/wireguard/docker-compose.yml b/tools/wireguard/docker-compose.yml new file mode 100644 index 0000000..6b1683f --- /dev/null +++ b/tools/wireguard/docker-compose.yml @@ -0,0 +1,46 @@ +services: + wireguard: + image: lscr.io/linuxserver/wireguard:latest + container_name: wireguard + cap_add: + - NET_ADMIN + - SYS_MODULE + environment: + - PUID=1000 + - PGID=1000 + - TZ=UTC + volumes: + - ./wireguard-config:/config + - /lib/modules:/lib/modules:ro + sysctls: + - net.ipv4.ip_forward=1 + - net.ipv4.conf.all.src_valid_mark=1 + restart: unless-stopped + healthcheck: + test: ["CMD", "ping", "-c", "1", "10.0.0.1"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 30s + networks: + vpn_net: + ipv4_address: 172.32.0.2 + + traefik: + image: traefik:v3.0 + container_name: traefik + restart: unless-stopped + depends_on: + wireguard: + condition: service_healthy + network_mode: service:wireguard + volumes: + - ./traefik:/etc/traefik + - ./letsencrypt:/letsencrypt + +networks: + vpn_net: + driver: bridge + ipam: + config: + - subnet: 172.32.0.0/24 diff --git a/tools/wireguard/traefik/dynamic.yml b/tools/wireguard/traefik/dynamic.yml new file mode 100644 index 0000000..25f7980 --- /dev/null +++ b/tools/wireguard/traefik/dynamic.yml @@ -0,0 +1,97 @@ +# ============================================================================= +# Traefik Dynamic Configuration +# This file defines your routers, services, and middlewares. +# +# HTTP → HTTPS redirection is handled globally in traefik.yml, so each service +# only needs a single router for HTTPS. +# +# Sections marked "No changes needed" are reusable building blocks. +# Sections marked "CONFIGURE" are where you add your own services. +# ============================================================================= + +http: + # --- No changes needed --------------------------------------------------- + middlewares: + https-headers: + # Required for services that need to know the original protocol + # (e.g. Mastodon, Matrix/Synapse) + headers: + customRequestHeaders: + X-Forwarded-Proto: "https" + + serversTransports: + # Use this for backend containers that use self-signed TLS certs + # (e.g. Nextcloud). Reference it in a service with: + # serversTransport: insecure-transport + insecure-transport: + insecureSkipVerify: true + # ------------------------------------------------------------------------- + + # --- CONFIGURE ----------------------------------------------------------- + routers: + # Basic service + my-service: + rule: "Host(`service.example.com`)" # <-- change domain + entryPoints: + - websecure + service: my-service + tls: + certResolver: letsencrypt + + # Service that needs X-Forwarded-Proto (e.g. Mastodon, Synapse) + my-service-with-headers: + rule: "Host(`other.example.com`)" # <-- change domain + entryPoints: + - websecure + service: my-service-with-headers + middlewares: + - https-headers + tls: + certResolver: letsencrypt + + # Service with a self-signed cert on the backend (e.g. Nextcloud) + my-https-backend: + rule: "Host(`secure.example.com`)" # <-- change domain + entryPoints: + - websecure + service: my-https-backend + tls: + certResolver: letsencrypt + + services: + my-service: + loadBalancer: + servers: + - url: "http://container-name:PORT" # <-- change container name and port + + my-service-with-headers: + loadBalancer: + servers: + - url: "http://container-name:PORT" # <-- change container name and port + + my-https-backend: + loadBalancer: + servers: + - url: "https://container-name:PORT" # <-- change container name and port + serversTransport: insecure-transport + # ------------------------------------------------------------------------- + +# ============================================================================= +# TCP — only needed for raw TCP services (game servers, etc.) +# Remove this section entirely if you don't need it. +# ============================================================================= +tcp: + # --- CONFIGURE ----------------------------------------------------------- + routers: + my-tcp-service: + rule: "HostSNI(`*`)" + entryPoints: + - my-tcp-entrypoint # <-- must match an entrypoint defined in traefik.yml + service: my-tcp-service + + services: + my-tcp-service: + loadBalancer: + servers: + - address: "container-name:PORT" # <-- change container name and port + # ------------------------------------------------------------------------- diff --git a/tools/wireguard/traefik/traefik.yml b/tools/wireguard/traefik/traefik.yml new file mode 100644 index 0000000..2ee3689 --- /dev/null +++ b/tools/wireguard/traefik/traefik.yml @@ -0,0 +1,45 @@ +# ============================================================================= +# Traefik Static Configuration +# You generally do not need to change anything in this file except the section +# marked with "CONFIGURE" below. +# ============================================================================= + +# --- No changes needed ------------------------------------------------------- +api: + dashboard: true + insecure: true # Dashboard on port 8080 - only accessible via WireGuard + +entryPoints: + web: + address: ":80" + http: + redirections: + entryPoint: + to: websecure + scheme: https + websecure: + address: ":443" + # Add extra TCP/UDP entrypoints here if you need to expose non-HTTP services + # my-tcp: + # address: ":PORT" + +providers: + file: + filename: /etc/traefik/dynamic.yml + watch: true + +tls: + options: + default: + sniStrict: true # Rejects TLS connections for unknown hostnames +# ----------------------------------------------------------------------------- + +# --- CONFIGURE --------------------------------------------------------------- +certificatesResolvers: + letsencrypt: + acme: + email: YOUR_EMAIL_HERE@EMAIL.COM # <-- change this + storage: /letsencrypt/acme.json + httpChallenge: + entryPoint: web +# ----------------------------------------------------------------------------- diff --git a/tools/wireguard/vps/ports.sh b/tools/wireguard/vps/ports.sh new file mode 100644 index 0000000..1a7e1bf --- /dev/null +++ b/tools/wireguard/vps/ports.sh @@ -0,0 +1,208 @@ +#!/bin/bash +# Manage port forwarding from VPS to home server via WireGuard + +set -e + +INTERFACE=$(ip route | grep default | awk '{print $5}' | head -n1) +HOME_SERVER="10.0.0.2" + +show_help() { + echo "Port Forwarding Manager" + echo "========================" + echo "Forward ports from VPS to home server via WireGuard tunnel." + echo "" + echo "Usage: $0 [options]" + echo "" + echo "Commands:" + echo " list Show all currently forwarded ports" + echo " add [protocol] Forward a port to home server" + echo " remove [protocol] Stop forwarding a port" + echo " help Show this help message" + echo "" + echo "Protocol options:" + echo " tcp - TCP only (default)" + echo " udp - UDP only" + echo " both - TCP and UDP" + echo "" + echo "Examples:" + echo " $0 list # Show all forwarded ports" + echo " $0 add 25565 # Forward Minecraft server (TCP)" + echo " $0 add 7777 udp # Forward UDP port 7777" + echo " $0 add 27015 both # Forward game server (TCP+UDP)" + echo " $0 remove 25565 # Stop forwarding port 25565" + echo " $0 remove 7777 udp # Stop forwarding UDP port 7777" + echo "" + echo "Notes:" + echo " - Ports 80 and 443 are reserved for Traefik (HTTP/HTTPS)" + echo " - Changes are saved automatically and persist after reboot" + echo " - Run as root (sudo)" +} + +show_add_usage() { + echo "Error: Missing port number" + echo "" + echo "Usage: $0 add [protocol]" + echo "" + echo "Arguments:" + echo " port Port number to forward (required)" + echo " protocol tcp (default), udp, or both" + echo "" + echo "Examples:" + echo " $0 add 25565 # Forward TCP port 25565" + echo " $0 add 7777 udp # Forward UDP port 7777" + echo " $0 add 27015 both # Forward both TCP and UDP" +} + +show_remove_usage() { + echo "Error: Missing port number" + echo "" + echo "Usage: $0 remove [protocol]" + echo "" + echo "Arguments:" + echo " port Port number to stop forwarding (required)" + echo " protocol tcp (default), udp, or both" + echo "" + echo "Examples:" + echo " $0 remove 25565 # Stop forwarding TCP port 25565" + echo " $0 remove 7777 udp # Stop forwarding UDP port 7777" + echo " $0 remove 27015 both # Stop forwarding both TCP and UDP" +} + +show_invalid_protocol() { + echo "Error: Invalid protocol '$1'" + echo "" + echo "Valid protocols:" + echo " tcp - TCP only (default)" + echo " udp - UDP only" + echo " both - TCP and UDP" +} + +list_ports() { + echo "=== Forwarded Ports ===" + echo "" + local found=0 + iptables -t nat -L PREROUTING -n 2>/dev/null | grep -E "dpt:" | grep "10.0.0.2" | \ + awk '{for(i=1;i<=NF;i++) if($i ~ /dpt:/) print $2, $i}' | \ + sed 's/dpt://' | \ + while read proto port; do + echo " $port ($proto)" + found=1 + done + + if [ $found -eq 0 ]; then + # Check again since subshell doesn't preserve variable + if ! iptables -t nat -L PREROUTING -n 2>/dev/null | grep -q "10.0.0.2.*dpt:"; then + echo " No ports currently forwarded (besides 80/443 for Traefik)" + fi + fi + echo "" +} + +add_port() { + local port=$1 + local proto=$2 + + echo "Adding $proto port $port -> $HOME_SERVER:$port" + iptables -t nat -A PREROUTING -i $INTERFACE -p $proto --dport $port -j DNAT --to-destination $HOME_SERVER:$port + iptables -A FORWARD -i $INTERFACE -o wg0 -p $proto --dport $port -j ACCEPT +} + +remove_port() { + local port=$1 + local proto=$2 + + echo "Removing $proto port $port" + iptables -t nat -D PREROUTING -i $INTERFACE -p $proto --dport $port -j DNAT --to-destination $HOME_SERVER:$port 2>/dev/null || echo " NAT rule not found" + iptables -D FORWARD -i $INTERFACE -o wg0 -p $proto --dport $port -j ACCEPT 2>/dev/null || echo " FORWARD rule not found" +} + +save_rules() { + echo "" + echo "Saving iptables rules..." + netfilter-persistent save >/dev/null 2>&1 + echo "Done! Changes will persist after reboot." +} + +# Main +case ${1:-} in + help|--help|-h) + show_help + ;; + list) + list_ports + ;; + add) + if [ -z "${2:-}" ]; then + show_add_usage + exit 1 + fi + PORT=$2 + PROTOCOL=${3:-tcp} + + case $PROTOCOL in + tcp) + add_port $PORT tcp + ;; + udp) + add_port $PORT udp + ;; + both) + add_port $PORT tcp + add_port $PORT udp + ;; + *) + show_invalid_protocol $PROTOCOL + exit 1 + ;; + esac + save_rules + ;; + remove) + if [ -z "${2:-}" ]; then + show_remove_usage + exit 1 + fi + PORT=$2 + PROTOCOL=${3:-tcp} + + case $PROTOCOL in + tcp) + remove_port $PORT tcp + ;; + udp) + remove_port $PORT udp + ;; + both) + remove_port $PORT tcp + remove_port $PORT udp + ;; + *) + show_invalid_protocol $PROTOCOL + exit 1 + ;; + esac + save_rules + ;; + "") + echo "Error: No command specified" + echo "" + echo "Usage: $0 [options]" + echo "" + echo "Commands:" + echo " list Show all forwarded ports" + echo " add [protocol] Forward a port" + echo " remove [protocol] Stop forwarding a port" + echo " help Show detailed help" + echo "" + echo "Run '$0 help' for more information." + exit 1 + ;; + *) + echo "Error: Unknown command '$1'" + echo "" + echo "Valid commands: list, add, remove, help" + echo "" + echo "Run '$0 help' for more information." + exit 1 + ;; +esac diff --git a/tools/wireguard/vps/setup.sh b/tools/wireguard/vps/setup.sh new file mode 100644 index 0000000..d3d4194 --- /dev/null +++ b/tools/wireguard/vps/setup.sh @@ -0,0 +1,57 @@ +#!/bin/bash +# VPS Setup Script - Run on your Debian VPS as root + +set -e + +echo "=== Installing WireGuard ===" +apt update +apt install -y wireguard + +echo "=== Generating Keys ===" +cd /etc/wireguard +umask 077 +wg genkey | tee privatekey | wg pubkey > publickey + +echo "" +echo "========================================" +echo "VPS Private Key (put in wg0.conf):" +cat privatekey +echo "" +echo "VPS Public Key (put in home server config):" +cat publickey +echo "========================================" +echo "" + +echo "=== Copy your wg0.conf to /etc/wireguard/wg0.conf ===" +echo "=== Then replace VPS_PRIVATE_KEY with the private key above ===" +echo "=== And replace HOME_PUBLIC_KEY with your home server's public key ===" +echo "" + +echo "=== Enabling IP Forwarding ===" +echo 'net.ipv4.ip_forward=1' > /etc/sysctl.d/99-wireguard.conf +sysctl -p /etc/sysctl.d/99-wireguard.conf + +echo "=== Setting up iptables rules ===" +# Get the main network interface (usually eth0 or ens3) +INTERFACE=$(ip route | grep default | awk '{print $5}' | head -n1) +echo "Detected interface: $INTERFACE" + +# Forward ports 80 and 443 to home server via WireGuard +iptables -t nat -A PREROUTING -i $INTERFACE -p tcp --dport 80 -j DNAT --to-destination 10.0.0.2:80 +iptables -t nat -A PREROUTING -i $INTERFACE -p tcp --dport 443 -j DNAT --to-destination 10.0.0.2:443 +iptables -A FORWARD -i $INTERFACE -o wg0 -p tcp --dport 80 -j ACCEPT +iptables -A FORWARD -i $INTERFACE -o wg0 -p tcp --dport 443 -j ACCEPT +iptables -A FORWARD -i wg0 -o $INTERFACE -m state --state RELATED,ESTABLISHED -j ACCEPT +iptables -t nat -A POSTROUTING -o wg0 -j MASQUERADE + +echo "=== Making iptables persistent ===" +apt install -y iptables-persistent +netfilter-persistent save + +echo "=== Enabling WireGuard service ===" +systemctl enable wg-quick@wg0 +echo "" +echo "=== After you update wg0.conf with keys, run: ===" +echo "systemctl start wg-quick@wg0" +echo "" +echo "=== Done! ===" diff --git a/tools/wireguard/vps/wg0.conf b/tools/wireguard/vps/wg0.conf new file mode 100644 index 0000000..21d55ba --- /dev/null +++ b/tools/wireguard/vps/wg0.conf @@ -0,0 +1,8 @@ +[Interface] +Address = 10.0.0.1/24 +ListenPort = 51820 +PrivateKey = VPS_PRIVATE_KEY + +[Peer] +PublicKey = HOMELAB_PUBLIC_KEY +AllowedIPs = 10.0.0.2/32 diff --git a/tools/wireguard/wireguard-config/wg0.conf b/tools/wireguard/wireguard-config/wg0.conf new file mode 100644 index 0000000..a32087d --- /dev/null +++ b/tools/wireguard/wireguard-config/wg0.conf @@ -0,0 +1,10 @@ +[Interface] +Address = 10.0.0.2/24 +PrivateKey = HOMELAB_PRIVATE_KEY + +[Peer] +# VPS public key (from VPS's wg genkey | wg pubkey) +PublicKey = VPS_PUBLIC_KEY +Endpoint = VPS_IP:51820 +AllowedIPs = 10.0.0.1/32 +PersistentKeepalive = 25