diff --git a/.gitignore b/.gitignore index 10c6b93..0e96c14 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,15 @@ -# Secrets and environment files +# Environment and secrets .env .env.* *.key tskey-* authkey* -# Tailscale data (never commit state) +# Tailscale state (never commit) tailscale/tailscale-data/ + +# OS / editor files +.DS_Store +*.swp +*.swo +*~ diff --git a/README.md b/README.md index 159395b..43f2200 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # {{Service}} with Tailscale Integration -![{{Service}} with Tailscale](https://damconsulting.llc/images/logo_yellow.svg "{{Service}}") +![{{Service}} with Tailscale](https://example.com/logo.svg "{{Service}}") This project sets up a {{Service}} instance with Tailscale VPN integration using Docker Compose. It creates a secure, private network connection for your {{Service}} instance using Tailscale. @@ -25,7 +25,7 @@ ts-{{service}}/ 1. **Clone the Repository** ```bash - git clone https://gitea.damconsulting.llc/DAM/ts-{{service}} + git clone https://gitea.example.com/org/ts-{{service}} cd ts-{{service}} ``` 2. Create Required Directories @@ -105,4 +105,55 @@ ts-{{service}}/ - Tailscale documentation: https://tailscale.com/kb/ - {{Service}} [documentation]({{service_docs}}) - {{Service}} [repository]({{service_repo}}) - - {{Service}} [linuxserve.io]({{service_lcsr}}) \ No newline at end of file + - {{Service}} [linuxserve.io]({{service_lcsr}}) +## Tailscale Serve Configuration + +This repo includes two serve configuration files: + +- `tailscale/config/serve.json` — Default (recommended for Tailscale with MagicDNS + certs) +- `tailscale/config/serve.headscale.json` — For Headscale or Tailscale without certs (HTTP only) + +### How to use + +**Tailscale (default):** +- No changes needed. The default `serve.json` will be used. + +**Headscale:** +1. Copy `serve.headscale.json` over `serve.json`: + ```bash + cp tailscale/config/serve.headscale.json tailscale/config/serve.json + ``` +2. Update the hostname in `serve.json` to match your service. + +After changing the serve config, restart the sidecar: +```bash +docker compose restart -ts +``` + +## Configuration + +### Environment Variables + +Copy `.env.example` to `.env` and fill in your values: + +```bash +cp .env.example .env +``` + +### Tailscale Serve Configuration + +This repo ships with two serve configuration options: + +| File | Use Case | Description | +|------|----------|-------------| +| `tailscale/config/serve.json` | Tailscale (default) | Supports both HTTP and HTTPS when MagicDNS + certs are configured | +| `tailscale/config/serve.headscale.json` | Headscale / no certs | HTTP-only on port 80 | + +**To switch to Headscale mode:** + +```bash +cp tailscale/config/serve.headscale.json tailscale/config/serve.json +docker compose restart vikunja-ts +``` + +Update the hostname in `serve.headscale.json` to match your service. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..be3280c --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,21 @@ +# Security Notes + +## Sensitive Files + +- `.env` — Contains your Tailscale/Headscale auth key and service configuration. **Never commit this file.** +- `tailscale/tailscale-data/` — Contains Tailscale node state and keys. **Never commit this directory.** + +## Capabilities + +This compose file adds the following capabilities to the Tailscale sidecar: + +- `net_admin` — Required for Tailscale to manage network interfaces and routes. + +These capabilities are necessary for Tailscale to function but increase the attack surface if the container is compromised. + +## Recommendations + +- Use a dedicated, limited-scope auth key for each service. +- Regularly rotate auth keys. +- Review Headscale/Tailscale ACLs to ensure services only have the access they need. +- Keep the Tailscale Docker image reasonably up to date. diff --git a/docker-compose.yml b/docker-compose.yml index 1106e40..a68c6b1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,22 +1,51 @@ services: - {{service}}-ts: + vikunja-ts: image: tailscale/tailscale:latest - hostname: {{service}} - container_name: {{service}}-ts + hostname: vikunja + container_name: vikunja-ts environment: - TS_AUTHKEY=${TS_AUTHKEY} - TS_LOGIN_SERVER=${TS_LOGIN_SERVER} - TS_STATE_DIR=/var/lib/tailscale - TS_SERVE_CONFIG=/config/serve.json + - TS_EXTRA_ARGS=--login-server=${TS_LOGIN_SERVER} + - TS_DEBUG=1 volumes: - ./tailscale/tailscale-data:/var/lib/tailscale - ./tailscale/config:/config - /dev/net/tun:/dev/net/tun cap_add: - net_admin - - sys_module restart: unless-stopped - {{service-compose}} - network_mode: service:{{service}}-ts - depends_on: - - {{service}}-ts \ No newline at end of file + + db: + image: postgres:15 + environment: + POSTGRES_PASSWORD: testpassword123 + POSTGRES_USER: vikunja + POSTGRES_DB: vikunja + volumes: + - db-data:/var/lib/postgresql/data + network_mode: service:vikunja-ts + restart: unless-stopped + + vikunja: + image: vikunja/vikunja:0.24 + environment: + VIKUNJA_DATABASE_TYPE: postgres + VIKUNJA_DATABASE_HOST: 127.0.0.1 + VIKUNJA_DATABASE_USER: vikunja + VIKUNJA_DATABASE_PASSWORD: testpassword123 + VIKUNJA_DATABASE_DATABASE: vikunja + VIKUNJA_SERVICE_JWTSECRET: testpassword123 + VIKUNJA_SERVICE_PUBLICURL: ${VIKUNJA_SERVICE_PUBLICURL} + VIKUNJA_SERVICE_FRONTENDURL: ${VIKUNJA_SERVICE_FRONTENDURL} + volumes: + - ./files:/app/vikunja/files + depends_on: + - db + network_mode: service:vikunja-ts + restart: unless-stopped + +volumes: + db-data: diff --git a/tailscale/config/serve.headscale.json b/tailscale/config/serve.headscale.json new file mode 100644 index 0000000..27a1c25 --- /dev/null +++ b/tailscale/config/serve.headscale.json @@ -0,0 +1,16 @@ +{ + "TCP": { + "80": { + "HTTP": true + } + }, + "Web": { + "${TS_CERT_DOMAIN}:80": { + "Handlers": { + "/": { + "Proxy": "http://127.0.0.1:3456" + } + } + } + } +} diff --git a/tailscale/config/serve.json b/tailscale/config/serve.json index 121ffb8..4db16f8 100644 --- a/tailscale/config/serve.json +++ b/tailscale/config/serve.json @@ -1,19 +1,16 @@ { - "TCP": { - "443": { - "HTTPS": true - } - }, - "Web": { - "${TS_CERT_DOMAIN}:443": { - "Handlers": { - "/": { - "Proxy": "http://127.0.0.1:3000" - } + "TCP": { + "80": { + "HTTP": true + } + }, + "Web": { + "vikunja.example.com:80": { + "Handlers": { + "/": { + "Proxy": "http://127.0.0.1:3456" } } - }, - "AllowFunnel": { - "${TS_CERT_DOMAIN}:443": false } - } \ No newline at end of file + } +}