Skip to main content
Discover Packs Jobs Registries Requests Docs About GitHub

lhaig / pack-mastodon

Published by Lance Haig | View Source

pack
0 stars
Description
Deploy Mastodon, a self-hosted ActivityPub social network, to HashiCorp Nomad
License
MPL-2.0
Tags
#social #activitypub #mastodon
Download Status
Failed (v0.1.0) Feb 12, 21:42

failed to fetch job file: unsupported repository host or file not found

Versions
Select a version to see its documentation and run command.
Quick Run (v0.1.0)
ramble pack run lhaig/pack-mastodon@v0.1.0
README
# Mastodon Nomad Pack Deploy [Mastodon](https://joinmastodon.org/), a self-hosted ActivityPub social network, to HashiCorp Nomad via [Ramble](https://ramble.openwander.org/). Mastodon consists of three components co-located in a single Nomad group: the web UI (Puma), a streaming API (Node.js), and background workers (Sidekiq). PostgreSQL and Redis sidecars are included by default but can be replaced with external services. ## Prerequisites 1. **Host directories** created on Nomad clients: ```bash mkdir -p /opt/mastodon/postgres mkdir -p /opt/mastodon/media # only if not using S3 # If using Elasticsearch: mkdir -p /opt/mastodon/elasticsearch ``` 2. **Generate secrets** before your first deploy: ```bash # Secret key base and OTP secret docker run --rm ghcr.io/mastodon/mastodon:latest bin/rails secret docker run --rm ghcr.io/mastodon/mastodon:latest bin/rails secret # VAPID keys for web push docker run --rm ghcr.io/mastodon/mastodon:latest bin/rails mastodon:webpush:generate_vapid_key # ActiveRecord encryption keys (optional, recommended) docker run --rm ghcr.io/mastodon/mastodon:latest bin/rails db:encryption:init ``` ## Usage ### Basic deployment with sidecars ```bash ramble pack run mastodon \ -v local_domain="social.example.com" \ -v secret_key_base="<generated>" \ -v otp_secret="<generated>" \ -v vapid_private_key="<generated>" \ -v vapid_public_key="<generated>" \ -v postgres_password="changeme" ``` ### With Traefik routing ```bash ramble pack run mastodon \ -v local_domain="social.example.com" \ -v traefik_host="social.example.com" \ -v secret_key_base="<generated>" \ -v otp_secret="<generated>" \ -v vapid_private_key="<generated>" \ -v vapid_public_key="<generated>" \ -v postgres_password="changeme" ``` ### Using a variable file Create a `mastodon.vars.hcl` file with your configuration: ```hcl local_domain = "social.example.com" traefik_host = "social.example.com" secret_key_base = "<generated>" otp_secret = "<generated>" vapid_private_key = "<generated>" vapid_public_key = "<generated>" postgres_password = "changeme" ``` ```bash ramble pack run mastodon -f mastodon.vars.hcl ``` ### External PostgreSQL and Redis ```bash ramble pack run mastodon \ -v local_domain="social.example.com" \ -v secret_key_base="<generated>" \ -v otp_secret="<generated>" \ -v vapid_private_key="<generated>" \ -v vapid_public_key="<generated>" \ -v postgres_url="postgres://mastodon:pass@db.example.com:5432/mastodon_production" \ -v redis_url="redis://:pass@redis.example.com:6379/0" ``` ### With S3 storage and Elasticsearch ```bash ramble pack run mastodon \ -v local_domain="social.example.com" \ -v secret_key_base="<generated>" \ -v otp_secret="<generated>" \ -v vapid_private_key="<generated>" \ -v vapid_public_key="<generated>" \ -v postgres_password="changeme" \ -v s3_enabled=true \ -v s3_bucket="mastodon-media" \ -v s3_region="us-east-1" \ -v s3_access_key="<key>" \ -v s3_secret_key="<secret>" \ -v enable_elasticsearch=true ``` ### With SMTP ```bash ramble pack run mastodon \ -v local_domain="social.example.com" \ -v secret_key_base="<generated>" \ -v otp_secret="<generated>" \ -v vapid_private_key="<generated>" \ -v vapid_public_key="<generated>" \ -v postgres_password="changeme" \ -v smtp_server="smtp.mailgun.org" \ -v smtp_login="postmaster@social.example.com" \ -v smtp_password="<password>" \ -v smtp_from_address="notifications@social.example.com" ``` ## Post-deploy setup After the first deployment, run database migrations and create an admin account: ```bash # Run migrations ramble exec mastodon -task web -- bundle exec rails db:migrate # Create admin account ramble exec mastodon -task web -- bin/tootctl accounts create admin \ --email admin@social.example.com --confirmed --role Owner ``` ## Variables ### General | Variable | Description | Default | |----------|-------------|---------| | `job_name` | Override job name | `mastodon` | | `region` | Nomad region | `""` | | `datacenters` | Target datacenters | `["*"]` | | `count` | Number of instances | `1` | ### Mastodon Identity | Variable | Description | Default | |----------|-------------|---------| | `local_domain` | Domain for the instance | *required* | | `single_user_mode` | Redirect front page to first profile | `false` | | `mastodon_version` | Docker image tag | `v4.3.7` | ### Secrets | Variable | Description | Default | |----------|-------------|---------| | `secret_key_base` | Session cookie secret | *required* | | `otp_secret` | 2FA TOTP secret | *required* | | `vapid_private_key` | Web push private key | *required* | | `vapid_public_key` | Web push public key | *required* | | `active_record_encryption_primary_key` | AR encryption primary key | `""` | | `active_record_encryption_deterministic_key` | AR encryption deterministic key | `""` | | `active_record_encryption_key_derivation_salt` | AR encryption salt | `""` | ### PostgreSQL | Variable | Description | Default | |----------|-------------|---------| | `enable_postgres` | Deploy PostgreSQL sidecar | `true` | | `postgres_url` | External PostgreSQL URL (disables sidecar) | `""` | | `postgres_user` | Sidecar username | `mastodon` | | `postgres_password` | Sidecar password | `""` | | `postgres_db` | Database name | `mastodon_production` | | `postgres_version` | Docker image tag | `16-alpine` | | `postgres_cpu` | CPU in MHz | `300` | | `postgres_memory` | Memory in MB | `512` | | `postgres_host_data_path` | Host path for data | `/opt/mastodon/postgres` | ### Redis | Variable | Description | Default | |----------|-------------|---------| | `enable_redis` | Deploy Redis sidecar | `true` | | `redis_url` | External Redis URL (disables sidecar) | `""` | | `redis_password` | Sidecar password | `""` | | `redis_version` | Docker image tag | `7-alpine` | | `redis_cpu` | CPU in MHz | `200` | | `redis_memory` | Memory in MB | `256` | ### Elasticsearch | Variable | Description | Default | |----------|-------------|---------| | `enable_elasticsearch` | Deploy Elasticsearch job | `false` | | `elasticsearch_url` | External ES URL | `""` | | `elasticsearch_version` | Docker image tag | `7.17.24` | | `elasticsearch_cpu` | CPU in MHz | `500` | | `elasticsearch_memory` | Memory in MB | `1024` | | `elasticsearch_host_data_path` | Host path for data | `/opt/mastodon/elasticsearch` | ### S3 Object Storage | Variable | Description | Default | |----------|-------------|---------| | `s3_enabled` | Use S3 for media files | `false` | | `s3_bucket` | Bucket name | `""` | | `s3_region` | AWS region | `us-east-1` | | `s3_endpoint` | S3-compatible endpoint | `""` | | `s3_access_key` | Access key ID | `""` | | `s3_secret_key` | Secret access key | `""` | | `s3_alias_host` | Custom media hostname | `""` | | `s3_permission` | ACL permission | `public-read` | ### Local Media Storage | Variable | Description | Default | |----------|-------------|---------| | `media_host_path` | Host path for media (when S3 disabled) | `/opt/mastodon/media` | ### SMTP | Variable | Description | Default | |----------|-------------|---------| | `smtp_server` | SMTP hostname | `""` | | `smtp_port` | SMTP port | `587` | | `smtp_login` | SMTP username | `""` | | `smtp_password` | SMTP password | `""` | | `smtp_from_address` | Sender email | `notifications@example.com` | | `smtp_auth_method` | Auth method | `plain` | | `smtp_openssl_verify_mode` | TLS verify mode | `none` | | `smtp_enable_starttls` | Enable STARTTLS | `true` | ### Resources | Variable | Description | Default | |----------|-------------|---------| | `web_cpu` | Web CPU in MHz | `500` | | `web_memory` | Web memory in MB | `512` | | `web_concurrency` | Puma workers | `2` | | `max_threads` | Puma threads per worker | `5` | | `streaming_cpu` | Streaming CPU in MHz | `200` | | `streaming_memory` | Streaming memory in MB | `256` | | `sidekiq_cpu` | Sidekiq CPU in MHz | `500` | | `sidekiq_memory` | Sidekiq memory in MB | `512` | | `sidekiq_concurrency` | Sidekiq threads | `25` | ### Service Discovery | Variable | Description | Default | |----------|-------------|---------| | `register_service` | Register with Nomad | `true` | | `service_name` | Service name | `mastodon` | | `service_tags` | Service tags | `["mastodon", "activitypub"]` | | `traefik_host` | Traefik routing hostname | `""` | ## Jobs | Job | Type | Description | |-----|------|-------------| | `mastodon` | service | Main instance (web + streaming + sidekiq) | | `mastodon-elasticsearch` | service | Full-text search (only when `enable_elasticsearch=true`) | ## Architecture ``` +---------------------+ | Traefik | +----------+----------+ | +-----------------+------------------+ | | Host(domain) Host(domain) && PathPrefix(/api/v1/streaming) | | v v +------+-------+ +---------+--------+ | Web (Puma) | | Streaming | | :3000 | | (Node.js) | | /health | | :4000 | +-+----+-------+ +--------+---------+ | | | | +-----------------------------------+ | | v v +----+------+ +------+-----+ | PostgreSQL| | Redis | | :5432 | | :6379 | +----+------+ +------+-----+ | | v v [host volume] [in-memory] +-------------+ +--------------------+ | Sidekiq |------>| Elasticsearch (opt)| | (workers) | | :9200 | +------+------+ +--------+-----------+ | | v v [S3 or host vol] [host volume] ``` ## License MPL-2.0