{"id":20815295,"url":"https://github.com/sowoi/ghostcms2mastodon","last_synced_at":"2025-04-10T00:27:48.888Z","repository":{"id":63609962,"uuid":"569158242","full_name":"sowoi/ghostcms2mastodon","owner":"sowoi","description":"Send posts from GhostCMS to Mastodon.","archived":false,"fork":false,"pushed_at":"2023-12-04T20:09:27.000Z","size":297,"stargazers_count":4,"open_issues_count":6,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-02T04:37:28.597Z","etag":null,"topics":["docker","docker-compose","flask","ghost","ghost-cms","mastodon","python","webhook-server"],"latest_commit_sha":null,"homepage":"https://okxo.de/send-your-ghostcms-posts-to-mastodon/","language":"Python","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/sowoi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2022-11-22T07:58:11.000Z","updated_at":"2024-12-02T20:39:46.000Z","dependencies_parsed_at":"2023-02-02T13:46:45.636Z","dependency_job_id":"9e8d588e-8a59-4c6d-85a4-1534e255337e","html_url":"https://github.com/sowoi/ghostcms2mastodon","commit_stats":{"total_commits":67,"total_committers":2,"mean_commits":33.5,"dds":"0.29850746268656714","last_synced_commit":"c755fd1987acc3887df91698c5750c61ed874a62"},"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sowoi%2Fghostcms2mastodon","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sowoi%2Fghostcms2mastodon/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sowoi%2Fghostcms2mastodon/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sowoi%2Fghostcms2mastodon/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sowoi","download_url":"https://codeload.github.com/sowoi/ghostcms2mastodon/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248133208,"owners_count":21053190,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["docker","docker-compose","flask","ghost","ghost-cms","mastodon","python","webhook-server"],"created_at":"2024-11-17T21:21:01.313Z","updated_at":"2025-04-10T00:27:48.853Z","avatar_url":"https://github.com/sowoi.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ghostcms2mastodon\nSend posts from GhostCMS to Mastodon.\n\n![How it looks](https://raw.githubusercontent.com/sowoi/ghostcms2mastodon/main/SendPosts2Mastodon.png)\n\n\n# General design\nGhost CMS triggers new posts and sends a webhook with the new post to a local Python Flask instance.\\\nThe Flask script fetches the relevant data from the payload and creates a Mastodon post.\\\nWe use Mastodon.py for this.\\\nThe Flask script is secured by UWSGI and access control.\\\nAs a bonus, GhostCMS tags are converted to Mastodon hashtags.\n\n# Features\n- Once set up completely automated\n- Restricting access to trusted IPs\n- Encrypted transmission to Mastodon\n- Respecting Mastodon policies (no excessive ping queries, avoiding SPAM, etc.)\n- Extensive debugging\n\n# Remote use / security\nBy default, the webhook endpoint should not be accessible from outside. \\\nAccess to the webhook is unencrypted, because GhostCMS does not allow access (without major intervention) to self-signed certificates. \\\nIf you are not running the instance on the same server as Ghost CMS, you need to encrypt the connection via https (e.g. using a reverse proxy). \\\nYour GhostCMS must then be added to the trusted proxies list in .env\n\n# Prequistes\n- Mastodon access token \n- Custom integrations webhook in Ghost CMS\n- You need to add secrets to .secure folder or pass the secrets via docker run\n\n\n# Mastodon access token\nThe only check you need to set is at \"write:statuses\".\\\nLeave all others unchecked! \\\nThis container does not use any other settings and therefore does not need any other permissions!\n\n# Webhook endpoint\n http://**dockerIP**:5000/webhook\nYou can of course change this port via Docker or in the source code. \\\nIf you are using the docker compose setting with fixed ip, that would be the IP 10.9.9.99 \\\nOn bare metal installations it would be localhost/127.0.0.1.\n\n# Ghost CMS\nThe settings in Ghost CMS are done via custom integrations.\\\nThe event trigger is \"Post published\n\n# Create secrets\nSecrets are parsed to the folder .secrets in your docker folder:\n\n```\n.\n├── docker-compose.yml\n├── .secrets\n│   ├── MASTODON_ACCESS_TOKEN\n│   ├── MASTODON_BASE_URL\n│   ├── TRUSTED_PROXIES\n│   └── WEBHOOK_SECRET\n\n```\n\nPopulate the files in the .secrets directory as follows:\\\nCopy your Mastodon token to MASTODON_ACCESS_TOKEN.\\\nCopy your Webhook token from Ghost CMS to WEBHOOK_SECRET.\\\nEnter in MASTODON_BASE_URL the address of your Mastodon instance, e.g. https://mastodon.social .\\\nAt TRUSTED_PROXIES you enter a list of IPs that should have access to your webhook instance. \nBy default, only localhost and access via Docker subnet from the Docker compose example is entered with a fixed IP, i.e. 10.9.9.0/24.\\\n\n# Docker\n```\ndocker run -d -p 5000:5000/tcp \\\n-v \"${PWD}/.secrets/WEBHOOK_SECRET:/run/secrets/WEBHOOK_SECRET:ro\" \\\n-v \"${PWD}/.secrets/MASTODON_ACCESS_TOKEN:/run/secrets/MASTODON_ACCESS_TOKEN:ro\" \\\n-v \"${PWD}/.secrets/MASTODON_BASE_URL:/run/secrets/MASTODON_BASE_URL:ro\" \\\n-v \"${PWD}/.secrets/TRUSTED_PROXIES:/run/secrets/TRUSTED_PROXIES:ro\" \\\n--net webhookSubnet \\\n--ip 10.9.9.99 okxo/ghostcms2mastodon\n```\n\n\n\n# Docker compose\n```\nversion: '3.1'\n\nsecrets:\n  WEBHOOK_SECRET:\n    file: ${PWD}/.secrets/WEBHOOK_SECRET\n  MASTODON_ACCESS_TOKEN:\n    file: ${PWD}/.secrets/MASTODON_ACCESS_TOKEN\n  MASTODON_BASE_URL:\n    file: ${PWD}/.secrets/MASTODON_BASE_URL\n  TRUSTED_PROXIES:\n    file: ${PWD}/.secrets/TRUSTED_PROXIES\n    \nservices:\n  ghostcms2mastodon:\n    image: okxo/ghostcms2mastodon:latest\n    restart: always\n    ports:\n      - 127.0.0.1:5000:5000\n    secrets: [WEBHOOK_SECRET,MASTODON_ACCESS_TOKEN,MASTODON_BASE_URL,TRUSTED_PROXIES]\n    environment:\n       WEBHOOK_SECRET: /run/secrets/WEBHOOK_SECRET\n       MASTODON_ACCESS_TOKEN: /run/secrets/MASTODON_ACCESS_TOKEN\n       MASTODON_BASE_URL: /run/secrets/MASTODON_BASE_URL\n       TRUSTED_PROXIES: /run/secrets/TRUSTED_PROXIES\n    networks:\n      vpcbr:\n        ipv4_address: 10.9.9.99\n    tty: true\n\nnetworks:\n  vpcbr:\n     driver: bridge\n     ipam:\n       config:\n         - subnet: 10.9.9.0/24\n           gateway: 10.9.9.1\n```\nYou need to enter a fixed ip for the docker container. \\\ndocker compose up -d\n\n# NGINX reverse proxy\nCreate an upstream in /etc/nginx/nginx.conf\n\n```\n  upstream mastodonwebhook {\n  server 127.0.0.1:5000;\n  keepalive 64;\n  }\n```\n\nAdd webhook location to your GhostCMS NGINX conf (in sites-availabe or in conf.d folder):\n\n```\nlocation /webhook {\n        proxy_set_header Host $host;\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto $scheme;\n        proxy_set_header X-Forwarded-Host $http_host;\n        proxy_set_header X-Forwarded-Uri $request_uri;\n        proxy_set_header X-Forwarded-Ssl on;\n        proxy_redirect  http://  $scheme://;\n        proxy_http_version 1.1;\n        proxy_set_header Connection \"\";\n        proxy_cache_bypass $cookie_session;\n        proxy_no_cache $cookie_session;\n        proxy_buffers 64 256k;\n\n        # If behind reverse proxy, forwards the correct IP                                                                                                                                                                                                                                                                                                                                                                                                                      \n        set_real_ip_from 10.0.0.0/8;\n        set_real_ip_from 172.0.0.0/8;\n        set_real_ip_from 10.9.0.0/16;\n        set_real_ip_from 192.168.0.0/16;\n        set_real_ip_from fc00::/7;\n        real_ip_header X-Forwarded-For;\n        real_ip_recursive on;\n\n        proxy_pass http://mastodonwebhook;\n}\n\n```\nRestart Nginx.\n\n# Poetry\nDependencies are in pyproject.toml\n\n\n# Bare metal\n```\napt install python3-dev python3-venv \\\npip3 install -r requirements \\\npython3 -m venv webhook \u0026\u0026 source webhook/bin/activate \\\ncd webhook \\\ncp Pythonfiles and ini files to your webhook folder \\\nexport MASTODON_ACCESS_TOKEN='**Add_your_Access_Token_Here**' \\\nexport MASTODON_BASE_URL='**https://Add_your_Mastodon_URL_Here**' \\\nexport TRUSTED_PROXIES='**LIST of IPs with access to local webhook endpoint**'\\\n```\nstart uwsgi server: \n```\nuwsgi --socket 127.0.0.1:5000 --protocol=http -w wsgi:app\n```\n \n# Acknowledgements\nThis project uses https://github.com/halcy/Mastodon.py and would not be feasible without this advance work.\n\n# License\nLicensed under the terms of GNU General Public License v3.0. See LICENSE file.\n\n# Dev\nhttps://okxo.de","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsowoi%2Fghostcms2mastodon","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsowoi%2Fghostcms2mastodon","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsowoi%2Fghostcms2mastodon/lists"}