diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b4e87cf --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +#Files +.env diff --git a/06-quickstart-vid/01-nginx-basic/docker-compose.yaml b/06-quickstart-vid/01-nginx-basic/docker-compose.yaml index c564e05..d30d52c 100644 --- a/06-quickstart-vid/01-nginx-basic/docker-compose.yaml +++ b/06-quickstart-vid/01-nginx-basic/docker-compose.yaml @@ -15,8 +15,10 @@ services: - net_admin restart: unless-stopped nginx-authkey-test: + container_name: nginx-authkey-test image: nginx network_mode: service:tailscale-authkey1 volumes: ts-authkey-test: driver: local + name: ts-authkey-test diff --git a/06-quickstart-vid/02-stirlingpdf/stirling.json b/06-quickstart-vid/02-stirlingpdf/config/stirling.json similarity index 100% rename from 06-quickstart-vid/02-stirlingpdf/stirling.json rename to 06-quickstart-vid/02-stirlingpdf/config/stirling.json diff --git a/06-quickstart-vid/02-stirlingpdf/docker-compose.yaml b/06-quickstart-vid/02-stirlingpdf/docker-compose.yaml index a133a58..2ac8a4d 100644 --- a/06-quickstart-vid/02-stirlingpdf/docker-compose.yaml +++ b/06-quickstart-vid/02-stirlingpdf/docker-compose.yaml @@ -1,14 +1,16 @@ services: + +# Stirling PDF services stirling-ts: image: tailscale/tailscale:latest container_name: stirling-ts hostname: pdf environment: - - TS_AUTHKEY=tskey-client-kcRHZB3GxG11CNTRL-example?ephemeral=false + - TS_AUTHKEY=${TS_OAUTHKEY_SECRET_CLIENT}?ephemeral=false - "TS_EXTRA_ARGS=--advertise-tags=tag:container --reset" - #- TS_SERVE_CONFIG=/config/stirling.json + # - TS_SERVE_CONFIG=/config/stirling.json - TS_STATE_DIR=/var/lib/tailscale - - TS_USERSPACE=false + - TS_ACCEPT_DNS=true volumes: - ${PWD}/config:/config - stirling-ts:/var/lib/tailscale @@ -30,10 +32,17 @@ services: - DOCKER_ENABLE_SECURITY=false restart: unless-stopped -volumes: +volumes: +# When never used "driver: local" it will create a local volume by the Docker engine. +# Docker volumes are stored in /var/lib/docker/volumes/ on the host machine. +# Each volume is stored in a separate directory within this path, and Docker manages the lifecycle of these volumes, including creation, deletion, and cleanup. +# By using named volumes, you can easily manage and persist data across container restarts and updates without worrying about the underlying storage details. stirling-ts: driver: local + name: stirling-ts stirling-config: driver: local + name: stirling-config stirling-storage: driver: local + name: stirling-storage \ No newline at end of file diff --git a/06-quickstart-vid/combine-tailscale-stirlingpdf/config/stirling.json b/06-quickstart-vid/combine-tailscale-stirlingpdf/config/stirling.json new file mode 100644 index 0000000..37aa7f5 --- /dev/null +++ b/06-quickstart-vid/combine-tailscale-stirlingpdf/config/stirling.json @@ -0,0 +1,19 @@ +{ + "TCP": { + "443": { + "HTTPS": true + } + }, + "Web": { + "${TS_CERT_DOMAIN}:443": { + "Handlers": { + "/": { + "Proxy": "http://127.0.0.1:8080" + } + } + } + }, + "AllowFunnel": { + "${TS_CERT_DOMAIN}:443": false + } + } \ No newline at end of file diff --git a/06-quickstart-vid/combine-tailscale-stirlingpdf/docker-compose.yaml b/06-quickstart-vid/combine-tailscale-stirlingpdf/docker-compose.yaml new file mode 100644 index 0000000..73f727e --- /dev/null +++ b/06-quickstart-vid/combine-tailscale-stirlingpdf/docker-compose.yaml @@ -0,0 +1,73 @@ +services: + tailscale-authkey1: + image: tailscale/tailscale:latest + container_name: ts-authkey + hostname: banana + environment: + - TS_AUTHKEY=${TS_AUTHKEY} + - TS_STATE_DIR=/var/lib/tailscale + - TS_USERSPACE=false + volumes: + - ts-authkey:/var/lib/tailscale + devices: + - /dev/net/tun:/dev/net/tun + cap_add: + - net_admin + restart: unless-stopped + nginx-authkey-test: + container_name: nginx-authkey + image: nginx + network_mode: service:tailscale-authkey1 + +# Stirling PDF services + stirling-ts: + image: tailscale/tailscale:latest + container_name: stirling-ts + hostname: pdf + environment: + - TS_AUTHKEY=${TS_OAUTHKEY_SECRET_CLIENT}?ephemeral=false + - "TS_EXTRA_ARGS=--advertise-tags=tag:container --reset" + - TS_SERVE_CONFIG=/config/stirling.json + - TS_STATE_DIR=/var/lib/tailscale + - TS_ACCEPT_DNS=true + volumes: + - ${PWD}/config:/config + - stirling-ts:/var/lib/tailscale + devices: + - /dev/net/tun:/dev/net/tun + cap_add: + - net_admin + restart: unless-stopped + stirlingpdf: + image: frooodle/s-pdf:latest + container_name: stirlingpdf + network_mode: service:stirling-ts + depends_on: + - stirling-ts + volumes: + - stirling-config:/configs + - stirling-storage:/usr/share/tesseract-ocr/5/tessdata + environment: + - DOCKER_ENABLE_SECURITY=false + restart: unless-stopped + +volumes: +# When never used "driver: local" it will create a local volume by the Docker engine. +# Docker volumes are stored in /var/lib/docker/volumes/ on the host machine. +# Each volume is stored in a separate directory within this path, and Docker manages the lifecycle of these volumes, including creation, deletion, and cleanup. +# By using named volumes, you can easily manage and persist data across container restarts and updates without worrying about the underlying storage details. + +# # Tailscale volumes +# ts-authkey: +# driver: local +# name: ts-authkey +# Stirling PDF volumes + stirling-ts: + driver: local + name: stirling-ts + stirling-config: + driver: local + name: stirling-config + stirling-storage: + driver: local + name: stirling-storage \ No newline at end of file diff --git a/06-quickstart-vid/stirling_tailscale_setup.md b/06-quickstart-vid/stirling_tailscale_setup.md new file mode 100644 index 0000000..5e69cb8 --- /dev/null +++ b/06-quickstart-vid/stirling_tailscale_setup.md @@ -0,0 +1,236 @@ +# Stirling PDF with Tailscale Docker Setup + +This guide cover how to run both nginx and Stirling PDF, behind the Tailscale using Docker Compose, if you like, you can use buth web application and PDF app with this [Docker Compose](./combine-tailscale-stirlingpdf/) setup. + + +> Important: DON'T pasted a real Tailscale auth key into ChatGPT, GitHub, logs, or screenshots. +In case you did, revoke it from the Tailscale admin console and generate a new one. + + +## Table tree +``` +06-quickstart-vid +├── 01-nginx-basic +│   └── docker-compose.yaml +├── 02-stirlingpdf +│   ├── config +│   │   └── stirling.json +│   └── docker-compose.yaml +├── combine-tailscale-stirlingpdf +│   ├── config +│   │   └── stirling.json +│   └── docker-compose.yaml +└── stirling_tailscale_setup.md +``` +## Table Content +- [Create a .env File](#1-create-a-env-file) +- [Generate a Tailscale Auth Key](#2-generate-a-tailscale-key) +- [Docker Compose Example](#3-docker-compose-example) +- [Stirling JSON Config](#4-stirling-json-config) +- [Enable MagicDNS and HTTPS Certificates](#5-enable-magicdns-and-https-certificates) +- [Verify Tailscale Connection](#6-verify-tailscale-connection) +- [Open Stirling PDF](#7-open-stirling-pdf) +- [Troubleshooting](#troubleshooting) +- [Tailscale GitHub](https://github.com/tailscale-dev/docker-guide-code-examples) +- [Srirling PDF GitHub](https://github.com/Stirling-Tools/Stirling-PDF) +- [Documents]() +--- +## 1. Create a .env File + +Create a `.env` file in the same directory as your `docker-compose.yaml`, to store your key: + +```bash +TS_AUTHKEY=tskey-auth-kc4MhA5vzX11CNTRL-example +TS_AUTHKEY_CLIENT=tskey-client-kcRHZB3GxG11CNTRL-example?ephemeral=false +``` + +Do not put the real key directly inside `docker-compose.yaml`. + +## 2. Generate a Tailscale Key + +Go to admin console https://login.tailscale.com/admin/settings/ + +- Create a 'Auth keys' for the NGINX Tailscale docker. + - Life time is up tp 90 days, [What is the diffrence between 'Auto Key' and 'OAuto key'?](#what-is-the-diffrence-between-auto-key-and-oauto-key) + +```text +Tailscale Admin Console -> Settings -> Keys -> Generate auth key +``` + +Recommended options: + +```text +Reusable: enabled +Ephemeral: disabled +Pre-approved: enabled +Expiration: short, for example 1 to 7 days +``` + +- Create a second key for the PDF tool. +```text +Tailscale Admin Console -> Settings -> Trust credentials -> Credential +``` + - Select OAuth (Description Optional) + - Under "Devices" -> Select 'Core' with a 'Write' access, and add the tag 'container'. + - Under "Keys" -> Select 'Auth Keys' with a 'Write' access, and add the tag 'container'. +--- + +### What is the diffrence between 'Auto Key' and 'OAuto key'? + +- Create both 'Auto Key' and 'OAuto key' for Tailscal and the pdf container. +Here's a comparison of the key differences between OAuth clients and auth keys in Tailscale: + +| Feature | Auth Keys | OAuth Clients | +|---|---|---| +| **Expiry** | Expire after 1–90 days (default 90) | Never expire | +| **Node ownership** | Node is owned by the user who generated the key | Node is owned by the tag assigned at creation | +| **Tags** | Optional | Required for created nodes | +| **API access** | Full API access | Scoped/limited access (e.g., `auth_keys:read`) | +| **Ephemeral nodes** | Not ephemeral by default | Nodes are ephemeral by default | + +Docs ref: [Auth Keys vs OAuth; Docker Guide](https://tailscale.com/blog/docker-tailscale-guide#using-oauth) + +### Key points to understand + +**Auth keys** (`tskey-auth-...`): +- Authenticate a device as the user who generated the key. +- Have a maximum lifespan of 90 days, but existing nodes remain authorized until their *node key* expires (default 180 days). +- Do not require tags (though tags can be applied). + +Docs Ref: [Auth Keys](https://tailscale.com/docs/features/access-control/auth-keys) + +**OAuth clients** (`tskey-client-...`): +- Provide delegated, scoped access to the Tailscale API — you can limit what actions are permitted (e.g., only creating auth keys, not modifying ACLs or DNS). +- Never expire, making them better suited for long-running automation. +- Require tags; nodes authenticated via OAuth are owned by those tags, not a user. +- By default, nodes registered via OAuth are marked **ephemeral** (removed when the container stops). To change this, append `?ephemeral=false` to the `TS_AUTHKEY` value. + +### Which should you use? + +- Use **auth keys** for simple, short-lived setups or when you don't need tags. +- Use **OAuth clients** for production automation, CI/CD pipelines, or anywhere you need non-expiring credentials with fine-grained access control. + +- Example of yaml file [docker-compose.yaml](./combine-tailscale-stirlingpdf/docker-compose.yaml): + +Do not expose your OAuth key inside of the yaml file, only at the `.env` file: + +```yaml +environment: + - TS_AUTHKEY=${TS_AUTHKEY} + - TS_AUTHKEY=${TS_OAUTHKEY_SECRET_CLIENT}?ephemeral=false +``` + +## 3. Docker Compose Example + +- Explained of the docker file, you can found at the officle Tailscal page: [https://tailscale.com/docs/features/containers/docker/how-to/connect-docker-container](https://tailscale.com/docs/features/containers/docker/how-to/connect-docker-container#docker-compose-example-details) + + - How to set an OAuth key, you can found at: https://tailscale.com/docs/features/oauth-clients + +## 4. Stirling JSON Config + +- The JSON file [stirling.json](./02-stirlingpdf/config/stirling.json), include a settings that allow https traffic using Tailscale certificate. + +Example: + +```json +{ + "TCP": { + "443": { + "HTTPS": true + } + }, + "Web": { + "${TS_CERT_DOMAIN}:443": { + "Handlers": { + "/": { + "Proxy": "http://127.0.0.1:8080" + } + } + } + }, + "AllowFunnel": { + "${TS_CERT_DOMAIN}:443": false + } + } +``` +## 5. Enable MagicDNS and HTTPS Certificates +- Go to https://login.tailscale.com/admin/dns + * Scroll to the buttun, and click on the "Enable MagicDNS", and "Enable HTTPS". + * Take your unique MagicDNS, and update into the `.env` file with a new line. + ```text + TS_CERT_DOMAIN=.ts.net + ``` + + - Example of full `.env` file: + ```text +TS_AUTHKEY=tskey-auth-NEW_KEY_HERE +TS_AUTHKEY_CLIENT=tskey-client-NEW_KEY_HERE +TS_CERT_DOMAIN=.ts.net +``` +- Wait for the certificate to apply for 3 minutes. + +## 6. Verify Tailscale Connection + +Check the Tailscale container logs: + +```bash +docker logs stirling-ts +``` + +Check Tailscale VPN device status: + +```bash +docker exec -it stirling-ts tailscale status +``` + +You should see the machine connected as: + +```text +aviela@MacBook-M1 config % docker exec -it stirling-ts tailscale status + +192.168.125.15 pdf pdf.magicDNS.ts.net linux - +192.168.132.88 banana tailscale@ linux - +10.16.86.61 iphone-15 tailscale@ iOS offline, last seen 6d ago +10.90.113.31 macbook-m1 tailscale@ macOS idle, tx 340 rx 268 +``` + +## 7. Open Stirling PDF + +Open this URL from your browser: + +```text +https://pdf.YOUR-TAILNET.ts.net +``` + +Use the full Tailscale MagicDNS name, not `localhost`. + +## Troubleshooting + +### Restart the Containers + +Run: + +```bash +docker compose down +docker compose up -d +``` + +### Check if Stirling is running + +```bash +docker logs stirlingpdf +``` + +### Check if Tailscale Serve loaded the config + +```bash +docker logs stirling-ts +``` + +### Confirm containers are running + +```bash +docker ps +``` + +@Write by https://github.com/Aviel-Amitay \ No newline at end of file diff --git a/README.md b/README.md index 9b138e0..f7bc985 100644 --- a/README.md +++ b/README.md @@ -11,4 +11,24 @@ This repository supports: These examples are compatible with both Docker and Podman. If you prefer to use Podman instead of Docker, you can use it as a drop-in replacement with no modifications to the examples. -For detailed information on Podman compatibility, see the [PODMAN_COMPATIBILITY.md](PODMAN_COMPATIBILITY.md) document. +For detailed information on Podman compatibility, see the [PODMAN_COMPATIBILITY.md](PODMAN_COMPATIBILITY.md) document. + +--- + +## 📖 Table of Contents + +Step | Folder | README +|-------|----------|------| +1 | +2 | +3 | +4 | +5 | +6 | [06-quickstart-vid](./06-quickstart-vid/) | [stirling_tailscale_setup.md](./06-quickstart-vid/stirling_tailscale_setup.md) +7 | + +--- + +## 🙌 Contributions + +PRs, issues, and suggestions are welcome!