diff --git a/.gitignore b/.gitignore index 2462b3c..e46a96d 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,11 @@ tskey-* authkey* tailscale/tailscale-data/ +homepage/images/ +homepage/config/logs/ +homepage/config/custom.css +homepage/config/custom.js +homepage/config/docker.yaml +homepage/config/kubernetes.yaml +homepage/config/proxmox.yaml + diff --git a/README.md b/README.md index 7815631..fed8882 100644 --- a/README.md +++ b/README.md @@ -1,111 +1,109 @@ # Homepage with Tailscale Integration -![Homepage with Tailscale](https://gethomepage.dev/assets/banner_light@2x.webp "Homepage with Tailscale Integration") +![Homepage with Tailscale](https://raw.githubusercontent.com/gethomepage/homepage/main/docs/assets/logo.png "Homepage") -This project sets up a Homepage instance with Tailscale VPN integration using Docker Compose. It creates a secure, private network connection for your homepage dashboard using Tailscale, while running the Homepage application from gethomepage.dev. +This project sets up a [Homepage](https://gethomepage.dev/) dashboard instance with Tailscale VPN integration using Docker Compose. -## Prerequisites +Homepage is a self-hosted dashboard that links to all your self-hosted services — perfect for giving you a single URL that shows the state of your homelab. -- Docker and Docker Compose installed on your system -- A Tailscale account and auth key (get one from https://login.tailscale.com/admin/authkeys) -- Basic understanding of Docker and networking concepts +## Quick Start (Tailscale) -## Project Structure -``` -ts-homepage/ -├── docker-compose.yml -├── tailscale/ -│ ├── tailscale-data/ # Persistent Tailscale state -│ └── config/ # Tailscale configuration files -└── homepage/ - └── config/ # Homepage configuration files -``` - -## Setup Instructions - -1. **Clone the Repository** +1. Copy the example environment file and fill in your values: ```bash - git clone https://gitea.damconsulting.llc/DAM/ts-homepage.git - cd ts-homepage + cp .env.example .env ``` -2. Create Required Directories - ```bash - mkdir -p tailscale/tailscale-data tailscale/config homepage/config - ``` -3. Configure Tailscale - - Make sure `TS_AUTHKEY` and `TS_LOGIN_SERVER` are set in your environment (or a local .env file) before running docker compose. - - Optionally, update the file in `tailscale/config/serve.json` if you need specific Tailscale serve configurations - - CAUTION: Changing `"${TS_CERT_DOMAIN}:443": false` to `true` will expose the service to the internet +2. Edit `.env` and set: + - `TS_AUTHKEY` — your Tailscale auth key + - `TZ` — your local timezone (e.g., `America/New_York`) +3. Start the stack: + ```bash + docker compose up -d + ``` +4. Customize the dashboard by editing `homepage/config/` files (see [Configuration](#configuration) below) +5. Access Homepage at `http://homepage..ts.net` -4. Configure Homepage - - Add your Homepage configuration files to homepage/config/ - - See https://gethomepage.dev/configs/ for configuration options - - The default setup allows all hosts (HOMEPAGE_ALLOWED_HOSTS: "*") +## Headscale -5. Start the Services - ```bash - docker compose up -d - ``` +If you're using Headscale instead of Tailscale: -## Services +1. Copy the example environment file: + ```bash + cp .env.example .env + ``` +2. Edit `.env` and set: + - `TS_AUTHKEY` — your Headscale auth key + - `TS_LOGIN_SERVER` — your Headscale server URL +3. Switch to the Headscale serve config: + ```bash + cp tailscale/config/serve.headscale.json tailscale/config/serve.json + ``` +4. Edit `serve.json` to use your actual domain. The default in this file uses `homepage.damconsulting.net` (Kevin's Headscale base domain) — replace it with your own if your setup differs. +5. Start the stack: + ```bash + docker compose up -d + ``` +6. Access Homepage at `http://homepage.yourdomain.com` -### homepage-ts (Tailscale) +## Configuration -- Runs Tailscale VPN client -- Image: tailscale/tailscale:latest -- Container name: homepage-ts -- Hostname: homepage -- Requires NET_ADMIN and SYS_MODULE capabilities -- Persists state in ./tailscale/tailscale-data -- Uses configuration from ./tailscale/config +### Switching Serve Configs -### homepage +| Environment | File to use | Notes | +|-------------------|--------------------------------------|-------| +| Tailscale (default) | `tailscale/config/serve.json` | Supports HTTP + HTTPS with certs | +| Headscale | `tailscale/config/serve.headscale.json` | HTTP only | -- Runs Homepage dashboard -- Image: ghcr.io/gethomepage/homepage:latest -- Container name: homepage -- Configuration stored in ./homepage/config -- Uses Tailscale's network stack (no direct port mapping) -- Depends on homepage-ts service +After changing the serve config, restart the sidecar: +```bash +docker compose restart homepage-ts +``` -## Usage +When the sidecar restarts, restart the homepage container too so it re-joins the new network namespace: +```bash +docker compose restart homepage +``` -- After starting the services your service should be available via tailnet at `https://homepage.{{YOUR_TAILNET_DOMAIN}}.ts.net` ie `https://homepage.tail12345.ts.net/` -- To manually get the Tailscale IP/hostname of your container: - ```bash - docker logs homepage-ts - ``` - Look for the Tailscale IP address in the logs. +### Dashboard Configuration -## Optional Features +Homepage reads its dashboard layout from YAML files in `./homepage/config/`: -- Uncomment the Docker socket volume mapping in the Homepage service to enable Docker integrations: - ```yaml - - /var/run/docker.sock:/var/run/docker.sock - ``` -- Uncomment and adjust the ports mapping if you need direct access (without Tailscale): - ```yaml - ports: - - 3000:3000 - ``` -- Stopping the Services - ```bash - docker compose down - ``` +- `settings.yaml` — global theme, layout, colors +- `services.yaml` — the services shown on the dashboard +- `bookmarks.yaml` — link groups +- `widgets.yaml` — info widgets (search bar, weather, time, etc.) +- `docker.yaml` — Docker container monitoring (if you mount the docker socket) + +The repo includes a starter `services.yaml` with placeholder entries. Edit the files to match the services you actually run on your tailnet (e.g., point entries to your other `ts-*` services at `http://.`, etc.). + +See https://gethomepage.dev/configs/ for the full reference. + +After editing config files, no restart is needed — Homepage hot-reloads. + +### Optional: Direct Host Access + +Uncomment the ports section in `docker-compose.yml` if you need direct access without Tailscale: +```yaml +ports: + - 3000:3000 +``` + +### Optional: Docker Socket Mount + +To let Homepage show running containers as widgets, uncomment this volume mount in `docker-compose.yml`: +```yaml +volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro +``` + +**Security note:** This gives the container read access to your Docker daemon. Only enable this on a trusted tailnet. -## Troubleshooting -- Check container logs: - ```bash - docker logs homepage-ts - docker logs homepage - ``` -- Ensure your Tailscale auth key is valid and not expired -- Verify the configuration files have proper permissions -- Make sure required directories exist before starting ## Notes -- The Homepage service uses the Tailscale service's network stack via network_mode: service:homepage-ts -- Direct port mapping is disabled by default as Tailscale handles the networking -- Services restart automatically unless explicitly stopped -- For more information: - - Tailscale documentation: https://tailscale.com/kb/ - - Homepage documentation: https://gethomepage.dev/ + +- `HOMEPAGE_ALLOWED_HOSTS: "*"` is set in the compose file because the Tailscale sidecar handles auth. If you expose Homepage outside the tailnet, restrict this to your actual hostnames. +- First-run shows the default "Welcome to Homepage" layout. Edit `services.yaml` to replace placeholders with your real services. + +## Links + +- Official site: https://gethomepage.dev/ +- Git repository: https://github.com/gethomepage/homepage +- Docker image: https://github.com/gethomepage/homepage/pkgs/container/homepage diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..7f79084 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,39 @@ +# Security Notes for ts-homepage + +This repository contains the configuration for deploying Homepage behind a Tailscale sidecar. + +## What's committed + +- `docker-compose.yml` — service definitions, image versions, env var references +- `.env.example` — template showing required env vars (no real secrets) +- `tailscale/config/serve.json` — Tailscale serve config (committed generic form) +- `tailscale/config/serve.headscale.json` — Headscale variant for testing +- `homepage/config/` — dashboard layout files (services, bookmarks, widgets) +- `README.md` — setup instructions + +## What is NOT committed + +- `.env` — contains real authkeys +- `tailscale/tailscale-data/` — Tailscale node identity state +- `homepage/images/` — uploaded images +- Any volume data + +The `.gitignore` at the repo root blocks accidental commits of these. + +## Rotation + +- If a `TS_AUTHKEY` was ever leaked, revoke it at https://login.tailscale.com/admin/authkeys (or your Headscale equivalent) and generate a new one. + +## Threat model + +This deployment assumes: +- The Mac mini is reachable only via Tailscale/Headscale +- All access to Homepage goes through the Tailscale sidecar (no exposed ports) +- The Tailnet itself is trusted +- If you mount the Docker socket, the Homepage container has read access to your Docker daemon — only enable this on a trusted tailnet + +If your threat model differs (e.g., you need to expose Homepage to the public internet), review the `AllowFunnel` setting in `tailscale/config/serve.json` and the Tailscale ACL controls carefully before proceeding. + +## Reporting + +If you find a security issue with this deployment pattern, contact kevin.riordan@damconsulting.llc. diff --git a/docker-compose.yml b/docker-compose.yml index ccbbb20..04504d3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,31 +1,39 @@ +# ========================================== +# REQUIRED: Tailscale sidecar (all ts-* services) +# ========================================== services: homepage-ts: image: tailscale/tailscale:latest hostname: homepage container_name: homepage-ts environment: - - TS_AUTHKEY={{YOUR_TAILSCALE_AUTHKEY}} + - 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} 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 + + # ========================================== + # REQUIRED: Homepage (single container, no DB) + # ========================================== homepage: image: ghcr.io/gethomepage/homepage:latest - container_name: homepage - # ports: - # - 3000:3000 - volumes: - - ./homepage/config:/app/config # Make sure your local config directory exists - # - /var/run/docker.sock:/var/run/docker.sock # (optional) For docker integrations environment: - # HOMEPAGE_ALLOWED_HOSTS: gethomepage.dev # required, may need port. See gethomepage.dev/installation/#homepage_allowed_hosts - HOMEPAGE_ALLOWED_HOSTS: "*" # required, may need port. See gethomepage.dev/installation/#homepage_allowed_hosts + # Required: comma-separated list of allowed hostnames / IPs. + # Use "*" to allow any (fine behind Tailscale, since Tailscale handles auth). + HOMEPAGE_ALLOWED_HOSTS: "*" + TZ: ${TZ:-UTC} + volumes: + - ./homepage/config:/app/config + depends_on: + - homepage-ts network_mode: service:homepage-ts - depends_on: - - homepage-ts \ No newline at end of file + restart: unless-stopped + diff --git a/homepage/config/bookmarks.yaml b/homepage/config/bookmarks.yaml new file mode 100644 index 0000000..76ee784 --- /dev/null +++ b/homepage/config/bookmarks.yaml @@ -0,0 +1,10 @@ +--- +# Homepage bookmarks: https://gethomepage.dev/configs/bookmarks/ +# Link groups shown in the bookmarks section. + +- Documentation: + - Homepage Docs: + - href: https://gethomepage.dev/ + - Tailscale Docs: + - href: https://tailscale.com/kb/ + diff --git a/homepage/config/services.yaml b/homepage/config/services.yaml new file mode 100644 index 0000000..17af3a0 --- /dev/null +++ b/homepage/config/services.yaml @@ -0,0 +1,35 @@ +--- +# Homepage services: https://gethomepage.dev/configs/services/ +# Edit to add your actual ts-* services running on the tailnet. +# Each service is a link on the dashboard. Point entries to actual tailnet URLs. + +- DAM Services: + - Vikunja: + href: http://{{service}}.yourdomain.com + description: Task management + icon: vikunja + - BookStack: + href: http://{{service}}.yourdomain.com + description: Documentation wiki + icon: bookstack + - Uptime Kuma: + href: http://{{service}}.yourdomain.com + description: Service monitoring + icon: uptime-kuma + - Focalboard: + href: http://{{service}}.yourdomain.com + description: Kanban boards + icon: focalboard + - Shiori: + href: http://{{service}}.yourdomain.com + description: Bookmark manager + icon: shiori + - FreshRSS: + href: http://{{service}}.yourdomain.com + description: RSS reader + icon: freshrss + - Stirling PDF: + href: http://{{service}}.yourdomain.com + description: PDF tools + icon: stirling-pdf + diff --git a/homepage/config/settings.yaml b/homepage/config/settings.yaml new file mode 100644 index 0000000..4925d71 --- /dev/null +++ b/homepage/config/settings.yaml @@ -0,0 +1,14 @@ +--- +# Homepage settings: https://gethomepage.dev/configs/settings/ +# Background, theme, layout, color scheme + +title: DAM Homelab +background: + opacity: 50 + blur: sm + saturation: 100 +theme: dark +color: slate +headerStyle: underlined +favicon: https://gethomepage.dev/icon.png + diff --git a/homepage/config/widgets.yaml b/homepage/config/widgets.yaml new file mode 100644 index 0000000..dbd48d1 --- /dev/null +++ b/homepage/config/widgets.yaml @@ -0,0 +1,18 @@ +--- +# Homepage widgets: https://gethomepage.dev/configs/widgets/ +# Info widgets shown at the top of the dashboard. + +- search: + provider: custom + url: https://www.google.com/search + +- resources: + cpu: true + memory: true + disk: / + +- datetime: + format: + timeStyle: short + dateStyle: medium + diff --git a/homepage/config/workspace/services.yaml b/homepage/config/workspace/services.yaml deleted file mode 100644 index 837ce28..0000000 --- a/homepage/config/workspace/services.yaml +++ /dev/null @@ -1,18 +0,0 @@ ---- -# For configuration options and examples, please see: -# https://gethomepage.dev/configs/services/ - -- My First Group: - - My First Service: - href: http://localhost/ - description: Homepage is awesome - -- My Second Group: - - My Second Service: - href: http://localhost/ - description: Homepage is the best - -- My Third Group: - - My Third Service: - href: http://localhost/ - description: Homepage is 😎 \ No newline at end of file diff --git a/tailscale/config/serve.headscale.json b/tailscale/config/serve.headscale.json new file mode 100644 index 0000000..bcb1451 --- /dev/null +++ b/tailscale/config/serve.headscale.json @@ -0,0 +1,17 @@ +{ + "TCP": { + "80": { + "HTTP": true + } + }, + "Web": { + "homepage.damconsulting.net:80": { + "Handlers": { + "/": { + "Proxy": "http://127.0.0.1:3000" + } + } + } + } +} + diff --git a/tailscale/config/serve.json b/tailscale/config/serve.json index 121ffb8..238c222 100644 --- a/tailscale/config/serve.json +++ b/tailscale/config/serve.json @@ -1,19 +1,29 @@ { - "TCP": { - "443": { - "HTTPS": true - } + "TCP": { + "80": { + "HTTP": true }, - "Web": { - "${TS_CERT_DOMAIN}:443": { - "Handlers": { - "/": { - "Proxy": "http://127.0.0.1:3000" - } + "443": { + "HTTPS": true + } + }, + "Web": { + "${TS_CERT_DOMAIN}:80": { + "Handlers": { + "/": { + "Proxy": "http://127.0.0.1:3000" } } }, - "AllowFunnel": { - "${TS_CERT_DOMAIN}:443": false + "${TS_CERT_DOMAIN}:443": { + "Handlers": { + "/": { + "Proxy": "http://127.0.0.1:3000" + } + } } - } \ No newline at end of file + }, + "AllowFunnel": { + "${TS_CERT_DOMAIN}:443": false + } +}