diff --git a/.gitignore b/.gitignore index aaadf73..a79d6c3 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,7 @@ go.work.sum # env file .env +!compose/.env # Editor/IDE # .idea/ diff --git a/README.md b/README.md index 7807116..3530f62 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,43 @@ # fmsg-docker Dockerised stack composing a full fmsg setup including: fmsgd, fmsgid, fmsg-webapi and fmsg-cli + +## Structure + +``` +fmsg-docker/ +├── docker/ +│ └── fmsgd/ +│ └── Dockerfile # builds fmsgd from source +│ +├── compose/ +│ ├── docker-compose.yml # full fmsg stack +│ └── .env # environment configuration +│ +└── README.md +``` + +## Getting Started + +1. Edit `compose/.env` and set your domain and a secure database password: + + ``` + FMSG_DOMAIN=example.com + PGPASSWORD=changeme + ``` + +2. From the `compose/` directory, start the stack: + + ``` + docker compose up -d + ``` + +3. fmsgd will be available on port `4930` (or the port set by `FMSG_PORT` in `.env`). + +## Services + +| Service | Description | +|---------------|--------------------------------------------------| +| `postgres` | PostgreSQL database shared by fmsgd and fmsgid | +| `fmsgid` | fmsg Id HTTP API — manages users and quotas | +| `fmsgd` | fmsg host — sends and receives fmsg messages | +| `fmsg-webapi` | fmsg Web API — HTTP interface to the fmsg stack | diff --git a/compose/.env b/compose/.env new file mode 100644 index 0000000..92b9073 --- /dev/null +++ b/compose/.env @@ -0,0 +1,23 @@ +# fmsg domain name this host serves, e.g. example.com +FMSG_DOMAIN=example.com + +# fmsgid HTTP port +FMSGID_PORT=8080 + +# fmsgd TCP port (default: 4930) +FMSG_PORT=4930 + +# Set to "true" to skip verifying this host's external IP is in the _fmsg DNS +# authorised IP set on startup. Useful for local/dev environments. +FMSG_SKIP_DOMAIN_IP_CHECK=false + +# Gin framework mode for fmsgid (release for production, debug for development) +GIN_MODE=release + +# PostgreSQL connection variables +# See: https://www.postgresql.org/docs/current/libpq-envars.html +PGHOST=postgres +PGPORT=5432 +PGDATABASE=fmsg +PGUSER=fmsg +PGPASSWORD=changeme # CHANGE THIS before deploying to production diff --git a/compose/docker-compose.yml b/compose/docker-compose.yml new file mode 100644 index 0000000..1505893 --- /dev/null +++ b/compose/docker-compose.yml @@ -0,0 +1,82 @@ +services: + + postgres: + image: postgres:18-alpine + restart: unless-stopped + environment: + POSTGRES_USER: ${PGUSER} + POSTGRES_PASSWORD: ${PGPASSWORD} + POSTGRES_DB: ${PGDATABASE} + volumes: + - postgres_data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${PGUSER}"] + interval: 10s + timeout: 5s + retries: 5 + + fmsgid: + build: + context: ../docker/fmsgid + dockerfile: Dockerfile + restart: unless-stopped + environment: + GIN_MODE: ${GIN_MODE:-release} + FMSGID_PORT: ${FMSGID_PORT:-8080} + PGHOST: postgres + PGPORT: 5432 + PGDATABASE: ${PGDATABASE} + PGUSER: ${PGUSER} + PGPASSWORD: ${PGPASSWORD} + PGSSLMODE: disable + depends_on: + postgres: + condition: service_healthy + + fmsgd: + build: + context: ../docker/fmsgd + dockerfile: Dockerfile + restart: unless-stopped + environment: + FMSG_DOMAIN: ${FMSG_DOMAIN} + FMSG_DATA_DIR: /opt/fmsg/data + FMSG_ID_URL: http://fmsgid:${FMSGID_PORT:-8080} + FMSG_SKIP_DOMAIN_IP_CHECK: ${FMSG_SKIP_DOMAIN_IP_CHECK:-false} + PGHOST: postgres + PGPORT: 5432 + PGDATABASE: ${PGDATABASE} + PGUSER: ${PGUSER} + PGPASSWORD: ${PGPASSWORD} + PGSSLMODE: disable + volumes: + - fmsg_data:/opt/fmsg/data + ports: + - "${FMSG_PORT:-4930}:4930" + depends_on: + postgres: + condition: service_healthy + fmsgid: + condition: service_started + + fmsg-webapi: + build: + context: ../docker/fmsg-webapi + dockerfile: Dockerfile + restart: unless-stopped + environment: + FMSG_DOMAIN: ${FMSG_DOMAIN} + FMSG_ID_URL: http://fmsgid:${FMSGID_PORT:-8080} + PGHOST: postgres + PGPORT: 5432 + PGDATABASE: ${PGDATABASE} + PGUSER: ${PGUSER} + PGPASSWORD: ${PGPASSWORD} + PGSSLMODE: disable + depends_on: + - fmsgd + - fmsgid + +volumes: + postgres_data: + fmsg_data: diff --git a/docker/fmsg-webapi/Dockerfile b/docker/fmsg-webapi/Dockerfile new file mode 100644 index 0000000..8d3d7e2 --- /dev/null +++ b/docker/fmsg-webapi/Dockerfile @@ -0,0 +1,27 @@ +FROM golang:1.25 AS builder + +WORKDIR /build + +RUN git clone https://github.com/markmnl/fmsg-webapi.git . && \ + cd src && \ + go build -o fmsg-webapi . + +FROM debian:bookworm-slim + +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + && rm -rf /var/lib/apt/lists/* + +RUN useradd -r -s /bin/false fmsg + +WORKDIR /opt/fmsg-webapi + +COPY --from=builder /build/src/fmsg-webapi /opt/fmsg-webapi/fmsg-webapi + +RUN chown -R fmsg:fmsg /opt/fmsg-webapi + +USER fmsg + +EXPOSE 8081 + +ENTRYPOINT ["/opt/fmsg-webapi/fmsg-webapi"] diff --git a/docker/fmsgd/Dockerfile b/docker/fmsgd/Dockerfile new file mode 100644 index 0000000..cb8033e --- /dev/null +++ b/docker/fmsgd/Dockerfile @@ -0,0 +1,28 @@ +FROM golang:1.25 AS builder + +WORKDIR /build + +RUN git clone https://github.com/markmnl/fmsgd.git . && \ + cd src && \ + go build -o fmsgd . + +FROM debian:bookworm-slim + +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + && rm -rf /var/lib/apt/lists/* + +RUN useradd -r -s /bin/false fmsg + +WORKDIR /opt/fmsgd + +COPY --from=builder /build/src/fmsgd /opt/fmsgd/fmsgd + +RUN mkdir -p /opt/fmsg/data && \ + chown -R fmsg:fmsg /opt/fmsgd /opt/fmsg/data + +USER fmsg + +EXPOSE 4930 + +ENTRYPOINT ["/opt/fmsgd/fmsgd", "0.0.0.0"] diff --git a/docker/fmsgid/Dockerfile b/docker/fmsgid/Dockerfile new file mode 100644 index 0000000..ae4a550 --- /dev/null +++ b/docker/fmsgid/Dockerfile @@ -0,0 +1,27 @@ +FROM golang:1.18 AS builder + +WORKDIR /build + +RUN git clone https://github.com/markmnl/fmsgid.git . && \ + cd src && \ + go build -o fmsgid . + +FROM debian:bookworm-slim + +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + && rm -rf /var/lib/apt/lists/* + +RUN useradd -r -s /bin/false fmsg + +WORKDIR /opt/fmsgid + +COPY --from=builder /build/src/fmsgid /opt/fmsgid/fmsgid + +RUN chown -R fmsg:fmsg /opt/fmsgid + +USER fmsg + +EXPOSE 8080 + +ENTRYPOINT ["/opt/fmsgid/fmsgid"]