diff --git a/deploy/.env.example b/deploy/.env.example new file mode 100644 index 000000000..6e59254c0 --- /dev/null +++ b/deploy/.env.example @@ -0,0 +1,35 @@ +# --- FreeScout VPS deployment --- +# Copy this file to deploy/.env and fill in values before running +# `docker compose --env-file deploy/.env up -d`. + +# Public URL FreeScout will be served from (no trailing slash). +APP_URL=https://help.example.com +# Host port the app container binds to. Point your reverse proxy here. +APP_PORT=8080 + +# FreeScout Docker image tag. Pin to a release in production +# (see https://hub.docker.com/r/nfrastack/freescout/tags). +FREESCOUT_IMAGE_TAG=latest + +# --- Database (MariaDB) --- +DB_NAME=freescout +DB_USER=freescout +DB_PASSWORD=change-me-strong-password +DB_ROOT_PASSWORD=change-me-strong-root-password + +# --- Initial admin user (created on first run only) --- +ADMIN_EMAIL=admin@example.com +ADMIN_PASSWORD=change-me-strong-password + +# --- Outbound mail (SMTP) --- +SMTP_HOST=smtp.example.com +SMTP_PORT=587 +SMTP_USER=postmaster@example.com +SMTP_PASS=change-me +# tls, ssl, or leave blank for none. +SMTP_ENCRYPTION=tls +SMTP_FROM_ADDRESS=help@example.com +SMTP_FROM_NAME=Nomad Support + +# IANA timezone, e.g. America/Los_Angeles +TIMEZONE=UTC diff --git a/deploy/README.md b/deploy/README.md new file mode 100644 index 000000000..e81854b6f --- /dev/null +++ b/deploy/README.md @@ -0,0 +1,39 @@ +# FreeScout VPS deployment + +Single-host Docker Compose stack for FreeScout (app + MariaDB). + +## Prerequisites + +- Docker Engine 24+ and the Compose plugin +- A DNS record pointing at the host +- A reverse proxy terminating TLS (Caddy, nginx, Traefik) that forwards to `APP_PORT` + +## Setup + +```bash +cp deploy/.env.example deploy/.env +# Edit deploy/.env — set APP_URL, DB and admin passwords, SMTP creds. + +docker compose -f deploy/docker-compose.yml --env-file deploy/.env up -d +docker compose -f deploy/docker-compose.yml --env-file deploy/.env logs -f app +``` + +First boot can take 2–5 minutes while the schema is created and assets are +warmed. Once the `app` container is healthy, FreeScout will be reachable at +`APP_URL` (the bootstrap admin is created automatically from +`ADMIN_EMAIL` / `ADMIN_PASSWORD`). + +## Operations + +- Update the image: bump `FREESCOUT_IMAGE_TAG` in `deploy/.env`, then + `docker compose -f deploy/docker-compose.yml --env-file deploy/.env pull && ... up -d`. +- App state (sessions, cache, uploaded files, installed Modules, generated + config) lives in `freescout_data` (`/data` inside the container). Logs live + in `freescout_logs`, and the database in `freescout_db`. Back all three up + off-box. +- Container image: + [`nfrastack/freescout`](https://github.com/nfrastack/container-freescout) + (the canonical successor to the legacy `tiredofit/freescout` image). +- Any additional FreeScout `.env` setting can be injected with the + `FREESCOUT_` prefix — e.g. `FREESCOUT_APP_TRUSTED_PROXIES=10.0.0.0/8` is + written into FreeScout's config as `APP_TRUSTED_PROXIES=10.0.0.0/8`. diff --git a/deploy/docker-compose.yml b/deploy/docker-compose.yml index cccad653b..7d5b32c31 100644 --- a/deploy/docker-compose.yml +++ b/deploy/docker-compose.yml @@ -1 +1,78 @@ -file:///tmp/b2_freescout_compose.txt \ No newline at end of file +# FreeScout — single-VPS deployment. +# +# Quick start: +# 1. cp deploy/.env.example deploy/.env +# 2. Fill in passwords, APP_URL, mail settings. +# 3. docker compose -f deploy/docker-compose.yml --env-file deploy/.env up -d +# 4. Browse to APP_URL and complete the FreeScout web installer. +# +# Reverse proxy (Caddy / nginx / Traefik) is expected to terminate TLS and +# forward to ${APP_PORT:-8080} on the host. + +services: + app: + image: nfrastack/freescout:${FREESCOUT_IMAGE_TAG:-latest} + container_name: freescout-app + restart: unless-stopped + depends_on: + db: + condition: service_healthy + ports: + - "${APP_PORT:-8080}:80" + environment: + CONTAINER_NAME: freescout-app + TIMEZONE: ${TIMEZONE:-UTC} + + APP_URL: ${APP_URL} + + DB_TYPE: mariadb + DB_HOST: db + DB_PORT: "3306" + DB_NAME: ${DB_NAME:-freescout} + DB_USER: ${DB_USER:-freescout} + DB_PASS: ${DB_PASSWORD} + + ADMIN_EMAIL: ${ADMIN_EMAIL} + ADMIN_PASS: ${ADMIN_PASSWORD} + + FREESCOUT_APP_TIMEZONE: ${TIMEZONE:-UTC} + FREESCOUT_MAIL_DRIVER: smtp + FREESCOUT_MAIL_HOST: ${SMTP_HOST:-} + FREESCOUT_MAIL_PORT: ${SMTP_PORT:-587} + FREESCOUT_MAIL_USERNAME: ${SMTP_USER:-} + FREESCOUT_MAIL_PASSWORD: ${SMTP_PASS:-} + FREESCOUT_MAIL_ENCRYPTION: ${SMTP_ENCRYPTION:-tls} + FREESCOUT_MAIL_FROM_ADDRESS: ${SMTP_FROM_ADDRESS:-} + FREESCOUT_MAIL_FROM_NAME: ${SMTP_FROM_NAME:-FreeScout} + volumes: + - freescout_data:/data + - freescout_logs:/logs + healthcheck: + test: ["CMD-SHELL", "exec 3<>/dev/tcp/127.0.0.1/80"] + interval: 30s + timeout: 10s + retries: 5 + start_period: 120s + + db: + image: mariadb:10.11 + container_name: freescout-db + restart: unless-stopped + environment: + MARIADB_DATABASE: ${DB_NAME:-freescout} + MARIADB_USER: ${DB_USER:-freescout} + MARIADB_PASSWORD: ${DB_PASSWORD} + MARIADB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} + volumes: + - freescout_db:/var/lib/mysql + healthcheck: + test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"] + interval: 15s + timeout: 5s + retries: 10 + start_period: 30s + +volumes: + freescout_data: + freescout_logs: + freescout_db: