No description
  • Shell 60.7%
  • Dockerfile 39.3%
Find a file Use this template
2026-04-07 19:11:15 +08:00
certs Fix Dockerfile security and container configuration issues 2026-04-07 00:34:10 +00:00
config Fix bugs, security issues, and improve README 2026-04-07 11:10:12 +00:00
content Update index.gmi 2026-04-06 19:57:11 +08:00
scripts Fix bugs, security issues, and improve README 2026-04-07 11:10:12 +00:00
.dockerignore Fix bugs, security issues, and improve README 2026-04-07 11:10:12 +00:00
.env.example Fix bugs, security issues, and improve README 2026-04-07 11:10:12 +00:00
.gitignore Update .gitignore 2026-04-06 20:21:53 +08:00
docker-compose.yml Fix bugs, security issues, and improve README 2026-04-07 11:10:12 +00:00
Dockerfile Fix bugs, security issues, and improve README 2026-04-07 11:10:12 +00:00
LICENSE Create LICENSE 2026-04-06 20:14:00 +08:00
README.md Fix bugs, security issues, and improve README 2026-04-07 11:10:12 +00:00

Gemini Capsule -- Molly Brown + Docker

A ready-to-use Docker setup for hosting a Gemini capsule with the Molly Brown server.

Features: automatic TLS certificate generation (with SAN), non-root execution, read-only content volume, health checks, and structured logging.

Quick Start

cp .env.example .env   # edit GEMINI_HOSTNAME if needed
docker compose up -d

Visit gemini://localhost:1965 with a Gemini client such as Lagrange.

Prerequisites

Configuration

Environment Variables

Variable Default Description
GEMINI_HOSTNAME localhost Domain for the TLS certificate CN/SAN and server config
GEMINI_PORT 1965 Host port mapped to the container's Gemini port

Place these in a .env file (see .env.example).

Adding Content

Put .gmi files (and any other files) in content/. They are served from /var/gemini inside the container. No restart is needed -- Molly Brown picks up new files automatically.

Changing the Domain

If you change GEMINI_HOSTNAME after initial setup, regenerate certificates:

docker compose down
rm certs/*.pem
# update GEMINI_HOSTNAME in .env
docker compose up -d

Changing the External Port

Set GEMINI_PORT in your .env file (e.g., GEMINI_PORT=8080). Docker Compose maps the host port to the container's internal port 1965. Gemini clients will need to connect to gemini://your.domain:8080.

Architecture

Two services in docker-compose.yml:

  1. setup -- one-shot Alpine container that generates config/molly.conf and self-signed TLS certificates in certs/.
  2. gemini-server -- Molly Brown built from source, running as non-root user gemini (UID 1000). Handles all TLS termination directly (no reverse proxy).

Security

  • Non-root user execution (UID 1000)
  • Content volume mounted read-only
  • Certificates directory mounted read-only in production container
  • Private key restricted to owner-only permissions (chmod 600)
  • Container runs with no-new-privileges and all capabilities dropped
  • Hostname input validated before use in certificate generation
  • Self-signed certificates are generated by default. For production, replace certs/cert.pem and certs/key.pem with CA-signed certificates. The setup container will not overwrite existing certificates.

Troubleshooting

Setup failed: check docker compose logs setup for errors.

Cannot connect: verify the port is open (ss -tlnp | grep 1965) and check docker compose logs gemini-server.

Regenerate certificates: stop containers, delete certs/*.pem, restart.

License

CC0 1.0 Universal -- Public Domain. Use freely without restrictions.