{"id":15167093,"url":"https://github.com/digitalcircuit/salt-mastodon","last_synced_at":"2026-02-05T06:03:05.167Z","repository":{"id":179256961,"uuid":"655995913","full_name":"digitalcircuit/salt-mastodon","owner":"digitalcircuit","description":"Mastodon social media instance, via SaltStack configuration management","archived":false,"fork":false,"pushed_at":"2025-06-03T03:44:32.000Z","size":111,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-18T05:52:27.372Z","etag":null,"topics":["fediverse","mastodon","salt","saltstack"],"latest_commit_sha":null,"homepage":"","language":"SaltStack","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/digitalcircuit.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-06-20T03:58:01.000Z","updated_at":"2025-06-03T03:44:34.000Z","dependencies_parsed_at":"2024-10-27T00:37:14.864Z","dependency_job_id":"ee1efebd-fdc4-492e-8c9e-b45f839e3377","html_url":"https://github.com/digitalcircuit/salt-mastodon","commit_stats":{"total_commits":10,"total_committers":1,"mean_commits":10.0,"dds":0.0,"last_synced_commit":"29c564190b6f4cc579050302937c8f7e0966af0f"},"previous_names":["digitalcircuit/salt-mastodon"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/digitalcircuit/salt-mastodon","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digitalcircuit%2Fsalt-mastodon","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digitalcircuit%2Fsalt-mastodon/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digitalcircuit%2Fsalt-mastodon/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digitalcircuit%2Fsalt-mastodon/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/digitalcircuit","download_url":"https://codeload.github.com/digitalcircuit/salt-mastodon/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digitalcircuit%2Fsalt-mastodon/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29114500,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-05T05:31:32.482Z","status":"ssl_error","status_checked_at":"2026-02-05T05:31:29.075Z","response_time":65,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fediverse","mastodon","salt","saltstack"],"created_at":"2024-09-27T05:24:34.821Z","updated_at":"2026-02-05T06:03:05.153Z","avatar_url":"https://github.com/digitalcircuit.png","language":"SaltStack","funding_links":[],"categories":[],"sub_categories":[],"readme":"Mastodon via Salt\n=================\n\nThis takes a stock Ubuntu 22.04/24.04 system and an S3-compatible object storage provider, and with Salt, turns this into a Mastodon federated social media instance, including Let's Encrypt certificates for encrypted connections and optional GPG-encrypted offsite backup.\n\nCurrently, this requires two main deployment steps due to the complications around automating version-dependent Mastodon migrations.\n\n*This is not endorsed by the official [Mastodon project](https://joinmastodon.org/)*\n\n***Work in progress:** features may change without warning.  Please read the commit log before updating production systems.*\n\n## Deployment\n\n* Customize the files in `pillar` to suit your environment\n  * See below for the minimum viable setup (e.g. local development)\n* Apply the salt state via `salt-call`\n  * Works with a [masterless minion Salt setup](https://docs.saltproject.io/en/latest/topics/tutorials/quickstart.html ), no need for master\n* Log in to the Mastodon service user (default: `mastodon`), and run the deployment\n```sh\nsudo --user mastodon --login\nbash\n./setup-mastodon.sh\n# The setup script will guide you on the interactive steps needed to configure Mastodon\n```\n* Copy newly generated secrets/keys into the [`pillar/server/web/app/mastodon.sls`](pillar/server/web/app/mastodon.sls) pillar file\n  * These should be specific to each instance and not reused\n* Re-apply the salt state via `salt-call`\n  * This ensures services that could not start before are restarted\n\nOn new Mastodon releases, re-run `setup-mastodon.sh`, run migration steps [as shared on the Mastodon release notes](https://github.com/mastodon/mastodon/releases ), and restart services.\n\n### Minimum viable setup (local development)\n\n1. Set your server hostnames\n\n[`pillar/server/hostnames.sls`](pillar/server/hostnames.sls):\n```yaml\n# Hostname details (optional/default configuration removed)\nserver:\n  # Hostnames\n  hostnames:\n    # Domains by certificate chain\n    # Main domain\n    cert-primary:\n      # Hostname visible to the world, used in SSL certs and branding\n      # /!\\ ---------------------------\n      # WARNING: This identifies your server and cannot be changed safely later\n      # See Mastodon documentation on \"LOCAL_DOMAIN\"\n      # -------------------------------\n      root: public.domain.here.example.com\n      # Hostname used for files/proxying S3 object storage\n      # /!\\ ---------------------------\n      # WARNING: This identifies media on your server and changing it will break past uploads\n      # See Mastodon documentation on \"S3_ALIAS_HOST\"\n      # -------------------------------\n      files: files.public.domain.here.example.com\n```\n\n2. Set up `certbot` for Let's Encrypt certificates, or disable it\n\n[`pillar/server/web/certbot.sls`](pillar/server/web/certbot.sls):\n```yaml\n# Certificate details for Let's Encrypt (optional/default configuration removed)\ncertbot:\n  # Replace dummy certificates with certificates from Let's Encrypt?\n  #\n  # NOTE - enabling certbot implies you agree to the Let's Encrypt\n  # Terms of Service (subscriber agreement).  Please read it first.\n  # https://letsencrypt.org/repository/#let-s-encrypt-subscriber-agreement\n  enable: True\n  # Use staging/test server to avoid rate-limit issues?\n  testing: False\n  # Account details\n  account:\n    # Email address for recovery\n    email: real-email-address@example.com\n```\n\n3. Set initial configuration for the Mastodon instance\n\n[`pillar/server/web/app/mastodon.sls`](pillar/server/web/app/mastodon.sls):\n```yaml\n# Mastodon configuration (optional/default configuration removed)\nserver:\n  web:\n    app:\n      # Mastodon instance configuration\n      mastodon:\n        # Run in single user mode?\n        # See https://docs.joinmastodon.org/admin/config/#single_user_mode\n        single_user_mode: False\n        # Secret keys\n        # Make sure to use `rake secret` to generate secrets\n        secrets:\n          secret_key_base: GENERATE_KEY_AFTER_DEPLOY\n          otp_secret: GENERATE_OTP_AFTER_DEPLOY\n        # Web push setup\n        # Generate with `rake mastodon:webpush:generate_vapid_key`\n        web_push:\n          vapid_private_key: GENERATE_VAPID_PRIVATE_AFTER_DEPLOY\n          vapid_public_key: GENERATE_VAPID_PUBLIC_AFTER_DEPLOY\n        # PostgreSQL database setup\n        database:\n          # NOTE: Changing database username will make prior backups fail to restore\n          # If database username and system username match, no password is needed, empty string (\"\") is fine\n          password: \"\"\n        # S3 object storage\n        # See https://docs.joinmastodon.org/admin/optional/object-storage/\n        object_storage:\n          hostname: S3_HOSTNAME_HERE\n          region: S3_REGION_HERE\n          endpoint: S3_ENDPOINT_HERE\n          name: mastodon-media\n          access_key_id: S3_ACCESS_KEY_ID_HERE\n          secret_access_key: S3_SECRET_ACCESS_KEY_HERE\n        # Email notifications\n        mail:\n          smtp_server: mail-provider.example.com\n          smtp_port: 587\n          smtp_username: EXAMPLE_USER\n          smtp_password: EXAMPLE_PASSWORD\n          smtp_from_address: notifications@example.com\n\n# Check the full \"pillar/server/web/app/mastodon.sls\" file for maintenance and further customization\n```\n\n## Usage\n\n### Default setup\n\n* [Mastodon](https://joinmastodon.org/) running via HTTPS on your own domain\n* Connection to S3-compatible object storage with local nginx caching to reduce API calls\n* Let's Encrypt for certificates with automated deployment and renewal, including reloading services\n* 2 GB swapfile for low-memory systems (e.g. 1 GB RAM)\n  * Initial deploy of Mastodon with asset compilation spikes memory usage\n\n### Configuration\n\n* Tune PostgreSQL performance (**recommended**)\n  * Modify [`pillar/server/storage/database.sls`](pillar/server/storage/database.sls) according to your system specifications.\n\n* Enable automatic Mastodon maintenance tasks (**recommended**)\n  * Modify [`pillar/server/web/app/mastodon.sls`](pillar/server/web/app/mastodon.sls) to enable the various tasks underneath `maintenance:`\n  * Set your `Media cache retention period` in your Mastodon server's Administration interface\n\n### Extra features\n\n#### Increase post and/or profile bio length limits\n* Allows for writing long posts and descriptions on your bio\n* Might break with Mastodon updates\n\n[`pillar/server/web/app/mastodon.sls`](pillar/server/web/app/mastodon.sls):\n```yaml\n# Mastodon configuration\nserver:\n  web:\n    app:\n      # Mastodon instance configuration\n      mastodon:\n        # [...existing configuration here...]\n        #\n        # Advanced instance customization\n        instance_config:\n          accounts:\n            max_bio_characters: 500\n            # Max characters for user profile bio (remove this for upstream default)\n          statuses:\n            max_characters: 500\n            # Max characters per post (remove this for upstream default)\n```\n\n#### Report system status via Telegraf to a remote metrics server\n* Configure [`pillar/server/metrics.sls`](pillar/server/metrics.sls) with metrics server details\n* Example receiving setup: Grafana + Telegraf HTTP Listener + InfluxDB\n\n#### Set up daily automatic, PGP-encrypted backups\n* Configure [`pillar/common/backup/system.sls`](pillar/common/backup/system.sls) and (optionally) [`rclone-archive.sls`](pillar/common/backup/rclone-archive.sls) with upload script and encryption settings\n  * Example script given for use with [rclone](https://rclone.org/), enabling backup to many cloud/self-hosted services\n\n## Credits\n\n* [Mastodon](https://github.com/mastodon/mastodon) for the federated social media server\n* Inspiration from the [Mastodon Ansible playbook](https://github.com/mastodon/mastodon-ansible ) and the [Terraform/Ansible setup for Oracle Cloud](https://github.com/faevourite/mastodon-oracle-cloud-free-tier )\n* *Some credits in the individual files, too*\n* *If you're missing, let me know, and I'll fix it as soon as I can!*\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdigitalcircuit%2Fsalt-mastodon","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdigitalcircuit%2Fsalt-mastodon","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdigitalcircuit%2Fsalt-mastodon/lists"}