{"id":19163200,"url":"https://github.com/programmer-ke/replatform","last_synced_at":"2025-07-12T08:05:19.628Z","repository":{"id":58865793,"uuid":"523672662","full_name":"programmer-ke/replatform","owner":"programmer-ke","description":"Run your own websites and email accounts","archived":false,"fork":false,"pushed_at":"2024-11-27T10:55:49.000Z","size":165,"stargazers_count":7,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-11-27T11:34:46.794Z","etag":null,"topics":["ansible","debian","dovecot","email","linux","nginx","postfix","self-hosted","website"],"latest_commit_sha":null,"homepage":"","language":"Jinja","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/programmer-ke.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,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-08-11T10:03:44.000Z","updated_at":"2024-11-27T10:55:53.000Z","dependencies_parsed_at":"2024-01-01T13:54:36.621Z","dependency_job_id":"3c076d82-1028-4851-a180-5d146e67e2fa","html_url":"https://github.com/programmer-ke/replatform","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/programmer-ke%2Freplatform","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/programmer-ke%2Freplatform/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/programmer-ke%2Freplatform/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/programmer-ke%2Freplatform/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/programmer-ke","download_url":"https://codeload.github.com/programmer-ke/replatform/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":232400143,"owners_count":18517350,"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":["ansible","debian","dovecot","email","linux","nginx","postfix","self-hosted","website"],"created_at":"2024-11-09T09:14:27.870Z","updated_at":"2025-01-03T21:42:50.450Z","avatar_url":"https://github.com/programmer-ke.png","language":"Jinja","funding_links":[],"categories":[],"sub_categories":[],"readme":"# replatform\n\n![replatform logo](img/replatform.jpeg)\n\nRun your own websites and email accounts using a platform you control.\n\nThis project allows anyone with basic unix command-line skills to\nquickly setup and easily maintain websites and email accounts on\nDebian Linux.\n\nIt uses an [ansible][10] playbook to install and configure a server\nwith one or more domains on which you can host websites and any number\nof email accounts.\n\nAll packages used are installed from Debian repositories. This makes\nit much easier to stay up to date and secure, and reduces the work\nneeded to migrate to newer versions of Debian.\n\n[10]: https://docs.ansible.com/ansible/latest/getting_started/index.html\n\n## Features\n\n- Supports multiple domains for email accounts and websites on one server\n- Just one command to setup the entire system: `ansible-playbook site.yml`\n- Critical security updates automatically installed once the server is up and running\n- DKIM, SPF, DMARC configured reducing the probability of sent mail being marked as spam\n- Automated, free TLS certificate via [Let's Encrypt][7] to secure your websites and emails\n- Out of the box server side web analytics via [goaccess][9]\n\n[7]: https://letsencrypt.org/\n[9]: https://goaccess.io/\n\n## Prerequisites\n\n- You have your domain name(s) registered under the domain name\n  provider(s) of your choice\n- You have root access to a Debian 11 linux server (see bottom of page\n  for a good deal)\n\n## Steps\n\n### DNS Setup\n\nLet's say we want to host two domain names, `example.com` and\n`example.org`.\n\n1) Server Hostname\n\nWe'll first set up a subdomain on one of the domain names as our\nserver hostname.\n\nFor this example we'll use `example.org`. Add the following records to\n`example.org` to map the subdomain to the public ipv4 and ipv6\n(optional) addresses associated with the server.\n\n| name                   | type | value                    | ttl  | remarks                |\n|------------------------|------|--------------------------|------|-------------------------|\n| myplatform.example.org | A    | 192.168.3.3              | 3600 | ipv4 address            |\n| myplatform.example.org | AAAA | fe80::1ff:fe23:4567:890a | 3600 | ipv6 address (optional) |\n\nYou can use any name in the place of `myplatform`, but keep it\nconsistent throughout the process below. The TTL value can be any\nreasonable number, the DNS provider may pre-fill it for you.\n\nDepending on the domain host's interface, you may need to add a `.`\n(dot) character after the name in the domain record.\n\nIf you're not sure how to add any of the records, just search online\nhow to add the type of record (A, AAAA, MX etc..) on your dns provider,\nthey probably have a tutorial of that somewhere.\n\n2) Domain and subdomain mappings\n\nWe then add the following records for `example.org`:\n\n| name          | type | value                    | ttl  | remarks                                        |\n|---------------|------|--------------------------|------|-------------------------------------------------|\n| *.example.org | A    | 192.168.3.3              | 3600 | Map all subdomains to the server's ipv4 address |\n| *.example.org | AAAA | fe80::1ff:fe23:4567:890a | 3600 | Map all subdomains to the server's ipv6 address |\n| example.org   | A    | 192.168.3.3              | 3600 | Map root domain to server's ipv4 address        |\n| example.org   | AAAA | fe80::1ff:fe23:4567:890a | 3600 | Map root domain to server's ipv6 address        |\n\nand the same for `example.com`:\n\n| name          | type | value                    | ttl  | remarks                                        |\n|---------------|------|--------------------------|------|-------------------------------------------------|\n| *.example.com | A    | 192.168.3.3              | 3600 | Map all subdomains to the server's ipv4 address |\n| *.example.com | AAAA | fe80::1ff:fe23:4567:890a | 3600 | Map all subdomains to the server's ipv6 address |\n| example.com   | A    | 192.168.3.3              | 3600 | Map root domain to server's ipv4 address        |\n| example.com   | AAAA | fe80::1ff:fe23:4567:890a | 3600 | Map root domain to server's ipv6 address        |\n\n3) Mail Exchange Records\n\nNow we need to designate the server hostname set in step 1 above as\nthe mail server for each of the domains. So for `example.org` we\nadd the following:\n\n| name        | type | value                  | priority | ttl  | remarks                                                               |\n|-------------|------|------------------------|----------|------|------------------------------------------------------------------------|\n| example.org | MX   | myplatform.example.org | 10       | 3600 | Priority can be any value, since we're only specifying one mail server |\n\nand the same for `example.com`. Note that the value is the same in both:\n\n| name        | type | value                  | priority | ttl  | remarks                                                               |\n|-------------|------|------------------------|----------|------|------------------------------------------------------------------------|\n| example.com | MX   | myplatform.example.org | 10       | 3600 | Priority can be any value, since we're only specifying one mail server |\n\n### Configure the server\n\n- It is generally recommended to use an SSH key to log into the server\n  instead of a password.  The first step will therefore be setting up\n  an SSH key.\n  If you are in a situation where you cannot set up one\n  e.g. when using a shared computer, skip this step and after cloning\n  this repo below, edit [ssh.yml](ssh.yml) and set both\n  `PasswordAuthentication` and `ChallengeResponseAuthentication` to\n  `yes` instead of `no`. Otherwise, password-based authentication will be disabled\n  and without an SSH key, you'll be locked out of the server.\n\n  - Generate an ssh key pair on your local device if you do not already\n\thave one (passphrase recommended) and copy the public key to the\n\tserver. More info [here][0].\n\n  - Copy it to the server with `ssh-copy-id root@myplatform.example.org`\n\n\t[0]: https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent\n\n  - Check that you can ssh into the server without being prompted for the\n\tpassword using `ssh root@myplatform.example.org`.\n\n- Make sure the server is up-to-date by running the following commands\n  - `apt update`\n  - `apt full-upgrade`\n\n- Reboot the server and then SSH back in again after a few seconds to make sure you are\n  modifying the server from a clean slate.\n  - `reboot`\n\n- Install `git` and `ansible` packages with the following command\n  - `apt install git ansible`\n\n- Clone this repo and navigate into it like so\n  - `git clone https://github.com/programmer-ke/replatform.git`\n  - `cd replatform`\n\n- Run the following ansible command to setup the server\n  `ansible-playbook site.yml`. The first time you run this, it will\n  place a variables file in the following location on the server:\n  `/root/private_vars/vars.yml` and exit\n\n- Edit this file with the correct variables such as the server\n  hostname (The value you set for `myplatform.example.org` above), the\n  external ipv4 address, ipv6 address if you have one, the domains you\n  want to host, etc. Be careful not to share this file as it has\n  secrets such as passwords. You can even encrypt it if you're a more\n  advanced user of ansible. Read about that [here][1]\n  \n  If you are unsure how to edit the file, use the [nano][2] editor that\n  is already installed with debian.\n\n  [1]: https://docs.ansible.com/ansible/latest/user_guide/vault.html\n  [2]: https://linuxize.com/post/how-to-use-nano-text-editor/\n\n- Run the playbook command again in the `replatform` directory to\n  proceed with set up. If you have a fast internet connection from\n  your server it should only take a few minutes to complete.\n\n  - `ansible-playbook site.yml`\n\n  If you encrypted the file above, add the\n  option `--ask-vault-pass` and enter the encryption password when\n  prompted.\n\n### Final Steps after Server configuration\n\nNow that server configuration is complete, we need to configure\nadditional domain settings with server generated values, and set up\nemail client software to start receiving email.\n\n#### Configure DNS TXT records\n\nThe configuration process generated some information that we need to\nadd as TXT records to the configured domains.\n\nThese will be useful for validating your email messages to other mail\nservers and reduce the probability of being marked as spam.\n\nMove into the directory they have been placed in:\n\n`cd /root/dns_txt_records`\n\nEach file name begins with the associated domain. There are 3 types\nfor each domain in the following pattern:\n\n- `example.org_dkim.txt` for the DKIM TXT record\n- `example.org_dmarc.txt` for the DMARC TXT record\n- `example.org_spf.txt` for the SPF TXT record.\n\nWe'll add the content of each file as a TXT record on the relevant\ndomain. Each file has a single line that starts with the hostname,\nfollowed by space, then the rest of the line as the value for the TXT\nrecord.\n\nWe add them as follows for each type of TXT record\n\n| Type  | hostname                       | value                                                      |\n|-------|--------------------------------|------------------------------------------------------------|\n| DKIM  | default._domainkey.example.org | v=DKIM1;h=sha256;k=rsa;p=MIIBIjANB...DAQAB                 |\n| SPF   | example.org                    | v=spf1 mx a:myplatform.example.org -all                    |\n| DMARC | _dmarc.dataengineering.co.ke   | v=DMARC1; p=quarantine; rua=mailto:..; ruf=mailto:..; fo=1 |\n\nIn some cases, the service provider may pre-fill the domain name \nfor you, so only input the prefix for the hostname value e.g.\n\n`default._domainkey` for `default._domainkey.example.org`\n\nSet the 3 TXT records for each of the configured domains.\n\n#### Configure Reverse DNS\n\nAs part of email authentication, some receiving systems will check\nwhether the ip address resolves back to the mail server hostname i.e.\n`myplatform.example.org` in our example.\n\nHow this is set up varies by the server host, for example you could be\nrequired to name your server with the appropriate hostname\n(e.g. `myplatform.example.org`) and the record will be set up\nautomatically. Other hosts may require you to reach out to support to\nhave it manually configured.\n\nThe requirement here is that the reverse dns lookup on the ipv4 (and\noptionally ipv6) address will resolve back the the value set as server\nhostname above.\n\nThis further reduces the probability of your email messages being\nmarked as spam.\n\n#### Configure mail clients\n\nMail clients will need an incoming server configuration for receiving\nemail and an outging server configuration for sending email.\n\nBelow, we'll list configuration as required by [thunderbird][3], but should\nbe similar on most email clients.\n\n[3]: https://www.thunderbird.net\n\n##### Incoming server\n\nThere are two options for incoming mail:\n- IMAP\n   - Mail will be stored on the server and accessible via different\n     devices / mail clients with the correct credentials\n- POP3:\n   - Mail will be downloaded to the client and deleted from the\n     server.  Received email will be viewable only on the device /\n     client that downloads the email.\n\nRead more about SSL/TLS vs STARTTLS [here][4]\n\n[4]: https://www.mimecast.com/blog/ssl-vs-tls-vs-starttls-encryption/\n\nThe hostname value below is the same throughout as it is the \nmail server hostname as `myplatform.example.org` set above.\n\n###### IMAP\n\nSSL/TLS (preferred):\n\n| Setting               | Value                    |\n|-----------------------|--------------------------|\n| Protocol              | IMAP                     |\n| Hostname              | myplatform.example.org   |\n| Port                  | 993                      |\n| Connection Security   | SSL/TLS                  |\n| Authentication Method | Normal Password          |\n| Username              | jane.doe@example.com     |\n\nSTARTTLS:\n\n| Setting               | Value                    |\n|-----------------------|--------------------------|\n| Protocol              | IMAP                     |\n| Hostname              | myplatform.example.org   |\n| Port                  | 143                      |\n| Connection Security   | STARTTLS                 |\n| Authentication Method | Normal Password          |\n| Username              | john.doe@example.com     |\n\n###### POP3\n\nSSL/TLS (preferred):\n\n| Setting               | Value                    |\n|-----------------------|--------------------------|\n| Protocol              | POP3                     |\n| Hostname              | myplatform.example.org   |\n| Port                  | 995                      |\n| Connection Security   | SSL/TLS                  |\n| Authentication Method | Normal Password          |\n| Username              | john.doe@example.com     |\n\nSTARTTLS:\n\n| Setting               | Value                    |\n|-----------------------|--------------------------|\n| Protocol              | POP3                     |\n| Hostname              | myplatform.example.org   |\n| Port                  | 110                      |\n| Connection Security   | STARTTLS                 |\n| Authentication Method | Normal Password          |\n| Username              | jane.doe@example.com     |\n\nTo receive administrative email sent to the admin user, set the\nusername on the email client as `admin@\u003cserver hostname\u003e` e.g.\n`admin@myplatform.example.org`, and password will the whatever was\nspecified in `/root/private_vars/vars.yml`.\n\n##### Outgoing server\n\nSSL/TLS (preferred):\n\n| Setting               | Value                    |\n|-----------------------|--------------------------|\n| Hostname              | myplatform.example.org   |\n| Port                  | 465                      |\n| Connection Security   | SSL/TLS                  |\n| Authentication Method | Normal Password          |\n| Username              | john.doe@example.com     |\n\nSTARTTLS:\n\n| Setting               | Value                    |\n|-----------------------|--------------------------|\n| Hostname              | myplatform.example.org   |\n| Port                  | 587                      |\n| Connection Security   | STARTTLS                 |\n| Authentication Method | Normal Password          |\n| Username              | jane.doe@example.com     |\n\nAt this point, to check that email is well set up, you can send an\nemail to `check-auth@verifier.port25.com` from any of the hosted mail\naccounts (i.e. not including `admin@\u003cserver_hostname\u003e`). This is an\nautomated service that will reply with results showing that DKIM, SPF\nand RDNS are well set up.\n\nFor more troubleshooting if your outgoing mail is consistently being\nmarked as spam, use https://mxtoolbox.com/. IP address reputation\nissues is a common problem.\n\n#### Updating Website files\n\nAfter the playbook completes, when you point your browser to\neach of the web domains configured and you'll see a placeholder web\npage.\n\nIf you check in the server at the location `/var/www` you'll\nsee a directory for each domain, and a file named `index.html` in\neach of these directories. This is the placeholder that is created\nas the landing page for each domain.\n\nTo publish your websites, upload the collection of files that make up\nyour websites into these directories.  The only requirement is that\nthere should be a page named `index.html` that will be the landing\npage.\n\nA basic tutorial that can get you started on HTML/CSS can be found\n[here][5].\n\n[5]: https://easyhtmlcss.com/\n\nThe `scp` or `rsync` commands can be used to transfer files to the\nserver via SSH.\n\n#### Web analytics\n\nWeb analytics that will be regerated every few minutes can be accessed\non the browser at the server's hostname at `/report.html`\ne.g. `myplatform.example.org/report.html`\n\nThese are generated from the web server's logs, so you can get some\nanalytics without having visitors download JavaScript trackers.\n\n#### Email files in the server\n\nThe email folders for each user are stored under\n\n`/home/vmail/\u003cdomain\u003e/\u003cusername\u003e/Maildir`.\n\nThis may be useful if you want to backup emails to an external\nlocation.\n\n#### Maintenance\n\nBy default, the system is set up to automatically install critical\nsecurity updates released by the debian team and reboot if necessary.\nAn email notification will be sent to the `admin@\u003cserver hostname\u003e`\nemail address whenever this happens.\n\nSpam detection rules will also be updated on a daily basis by\nspamassasin.\n\nEvery time the setup command `ansible-playbook site.yml`, is run like\nwe did above, all new updates will be installed and you will be\nprompted to reboot if necessary.\n\n\n## High level technical overview\n\n### Recieving mail into inbox\n\nThe number(s) in brackets indicates the port(s) the process is listening on.\n\nOutside Network -\u003e smptd(25) -\u003e Postfix Queue -\u003e Dovecot lmtp (via\nunix pipe) -\u003e Virtual boxes or User boxes\n\n### Retrieving mail by mail client\n\nEmail client -\u003e dovecot-imapd(993 \u0026 143) -\u003e Virtual or system user mailbox\n\nEmail client -\u003e dovecot-pop3d(995 \u0026 110) -\u003e Virtual or system user mailbox\n\n### Submitting outgoing mail to server from mail client\n\nEmail client -\u003e smtpd(465) (ssl/tls) -\u003e postfix queue -\u003e smtp client -\u003e destination network\n\nEmail client -\u003e smtpd(587) (starttls) -\u003e postfix queue -\u003e smtp client -\u003e destination network\n\n## Technical considerations\n- While more experienced users may frown on this, we directly use the\n  root user to setup everything. Goal is to reduce friction as much as\n  possible for non-technical users.\n- For the same reason above, we run ansible directly on the server\n  instead of the typical use-case of using a different machine as\n  the control node.\n- All packages are from the default Debian repositories. This makes it\n  much easier to stay up to date by relying on the great Debian folks\n  for updates. Consider [donating][6] to Debian if you appreciate\n  their work.\n\n[6]: https://www.debian.org/donations\n\n## Testing Resources\n- SSL\n  - https://github.com/drwetter/testssl.sh\n  - https://www.immuniweb.com\n\n- Email\n  - http://www.jetmore.org/john/code/swaks/\n  - https://spamassassin.apache.org/gtube/\n  - https://mxtoolbox.com/\n\n## Credits\n\nInspired by the following projects:\n\n- Luke Smith's emailwiz: https://github.com/LukeSmithxyz/emailwiz\n- Landchad: https://landchad.net/\n- Sovereign: https://github.com/sovereign/sovereign\n\n## Looking For Affordable Servers?\n\nCheckout the following offers from Racknerd:\n\n- 1GB at [$10.99/year][11]\n- 1.5 GB at [$16.88/year][12]\n- 2.5 GB at [$23.88/year][13]\n\n[11]: https://my.racknerd.com/aff.php?aff=9677\u0026pid=838\n[12]: https://my.racknerd.com/aff.php?aff=9677\u0026pid=839\n[13]: https://my.racknerd.com/aff.php?aff=9677\u0026pid=840\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprogrammer-ke%2Freplatform","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fprogrammer-ke%2Freplatform","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprogrammer-ke%2Freplatform/lists"}