{"id":15718476,"url":"https://github.com/thekevjames/selfhost","last_synced_at":"2025-07-11T12:10:30.408Z","repository":{"id":186327308,"uuid":"675005761","full_name":"TheKevJames/selfhost","owner":"TheKevJames","description":"sources for all my selfhosted applications","archived":false,"fork":false,"pushed_at":"2025-07-04T00:53:13.000Z","size":449,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-07-04T01:33:40.822Z","etag":null,"topics":["selfhost"],"latest_commit_sha":null,"homepage":null,"language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TheKevJames.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.rst","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"ko_fi":"thekevjames"}},"created_at":"2023-08-05T13:11:39.000Z","updated_at":"2025-07-04T00:53:16.000Z","dependencies_parsed_at":null,"dependency_job_id":"942c8bae-3c81-46db-a354-95d4e2f798d7","html_url":"https://github.com/TheKevJames/selfhost","commit_stats":null,"previous_names":["thekevjames/selfhost"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/TheKevJames/selfhost","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheKevJames%2Fselfhost","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheKevJames%2Fselfhost/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheKevJames%2Fselfhost/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheKevJames%2Fselfhost/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TheKevJames","download_url":"https://codeload.github.com/TheKevJames/selfhost/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TheKevJames%2Fselfhost/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264804159,"owners_count":23666516,"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":["selfhost"],"created_at":"2024-10-03T21:53:11.248Z","updated_at":"2025-07-11T12:10:30.398Z","avatar_url":"https://github.com/TheKevJames.png","language":"Shell","funding_links":["https://ko-fi.com/thekevjames"],"categories":[],"sub_categories":[],"readme":"Selfhosted Platform\n===================\n\nBuilding up the things I selfhost as a source-controlled project. Goal here is\nto have a single source for configuring all the things -- or at least a single\nplace where it's all documented, when that's not possible.\n\nSetup\n-----\n\nInstall the relevant OS:\n\n* `Raspbian OS Lite`_ (pre-configure the wifi/hostname/ssh creds/etc before\n  writing the image to save effort, ``sudo raspi-config`` afterwards to\n  configure locale etc)\n* `Debian`_ (skip the additional packages, but `set up networking`_ and ``apt\n  install openssh-server``)\n\nConfigure your ssh keys (``ssh-copy-id $hostname``) and modify\n``/etc/ssh/sshd_config`` how you'd like (``PermitRootLogin no`` and\n``PasswordAuthentication no`` and pretty good improvements to the defaults).\n\nFrom there, reboot, ssh into the new machine, and::\n\n    sudo apt update -y\n    sudo apt install -y --no-install-recommends git\n    ssh-keygen -o -a 100 -t ed25519 -C \"KevinJames@thekev.in\" -f ~/.ssh/id_ed25519\n    git clone git@github.com:TheKevJames/selfhost ~/src/personal/selfhost\n    cd ~/src/personal/selfhost\n\nAfter this point, further steps depend on what functions this machine will\nprovide. First off, you probably want to mount `External Drives`_.\n\nOnce that's done, consider increasing your swap size and/or moving it onto one\nof those drives. This is especially important for low-memory systems or cases\nwhere your default swapfile lives on an SD card::\n\n    sudo apt update -y\n    sudo apt install -y --no-install-recommends dphys-swapfile\n\n    sudo dphys-swapfile swapoff\n    sudo vi /etc/dphys-swapfile\n    # CONF_SWAPFILE=/mnt/1tb/swap\n    # CONF_SWAPFACTOR=2\n    sudo mv /var/swap /mnt/1tb/swap\n\n    sudo dphys-swapfile setup\n    sudo dphys-swapfile swapon\n    sudo poweroff --reboot\n\nNow, install your container manager::\n\n    curl -fsSL https://get.docker.com -o get-docker.sh\n    sudo sh ./get-docker.sh\n    rm get-docker.sh\n    sudo groupadd docker\n    sudo usermod -aG docker $USER  # then logout / login\n\n    # on OSX, use colima for your Docker VM backend to avoid needing Docker for\n    # OSX:\n    https://github.com/abiosoft/colima\n\nOnce you've got a container manager, you can spin up everything defined in this\nrepo::\n\n    # pre-configure any relevant secrets\n    $ echo 'GOOGLE_CLIENT_ID=\"...\"' \u003e\u003e secrets/google.env\n    $ echo 'GOOGLE_CLIENT_SECRET=\"...\"' \u003e\u003e secrets/google.env\n\n    $ docker run --rm -it -v $PWD/cloudflared:/home/nonroot/.cloudflared cloudflare/cloudflared:latest tunnel login\n    $ docker run --rm -it -v $PWD/cloudflared:/home/nonroot/.cloudflared cloudflare/cloudflared:latest tunnel create selfhost\n    # modify cloudflared/config.yml with the new UUID\n    $ bin/cloudflare-expose example.com\n    $ bin/cloudflare-expose foo.example.com\n    $ bin/cloudflare-expose bar.example.com\n\n    # start images\n    $ make pull\n    $ make up -d\n\nIf this if the first time setup on a new machine and you want to migrate off a\nprevious one, using rsync on the relevant app directory should do the trick\n(before you start the relevant pod, but after shutting it down on the old\nhost!)::\n\n    rsync -aP oldhost:~/src/personal/selfhost/foobar/ foobar\n\nIf you did this, you may need to force Jellyfin to re-init by modifying\n``jellyfin/system.xml`` to have::\n\n    \u003cIsStartupWizardCompleted\u003efalse\u003c/IsStartupWizardCompleted\u003e\n\nThere are also some manual steps which you may want to do included below.\n\n* syncthing: visit the web UI and share any folders\n* pihole: ``docker logs pihole | grep random`` to get your password\n\nYou may also want to set up NTP. This is especially necessary if this machine\nwill be handling any auth, as handshakes will fail if your clock drifts too far\nout of sync::\n\n    sudo apt install ntp\n\nSyncthing\n~~~~~~~~~\n\nVisit ``:8384`` and set up any relevant shares.\n\nPi-Hole\n~~~~~~~\n\n::\n\n    # grab your admin password, configure settings in the web ui\n    docker logs pihole | grep random\n\n    # verify it works\n    dig -4 @NODEIPv4 example.com\n    # NODEIPv6=$( ip -6 addr show | awk '/global/ {print $2}'\n    dig -4 @NODEIPv6 example.com\n\n    # make your router/hosts/etc use pihole dns\n    # https://docs.pi-hole.net/main/post-install/\n    # note that if you want fallback DNS addresses, I like Cloudflare:\n    #   1.1.1.1, 1.0.0.1\n    #   2606:4700:4700::1111, 2606:4700:4700::1001\n    # verify it's configured:\n    dig -4 example.com | grep SERVER\n    dig -6 example.com | grep SERVER\n    # the SERVER should be using the IPv4 and IPv6 addresses you found earlier\n\nUpdates\n-------\n\nTo update the various components::\n\n    sudo apt update -y\n    sudo apt upgrade -y\n\n    cd ~/src/experiments/selfhost\n    git pull\n    make pull\n    make up -d\n\nExternal Drives\n---------------\n\nMachines generally either mount external drives physically and expose them via\nSamba, or mount them via Samba.\n\nPhysical Mounts\n~~~~~~~~~~~~~~~\n\nQuick walkthrough of how to fstab some external drives into being auto-mounted::\n\n    # find the drives\n    $ lsblk -f\n    NAME        FSTYPE FSVER LABEL  UUID                                 FSAVAIL FSUSE% MOUNTPOINT\n    sda\n    `-sda1      ext4   1.0          43162a5a-f1b2-441f-9d51-433bea2e113c\n    sdb\n    `-sdb1      ext4   1.0          b9479cb5-b306-430b-998d-3d793aadfde6\n\n    # set up the mount points\n    $ sudo mkdir /mnt/1tb /mnt/4tb\n\n    # auto-mount 'em at startup\n    $ echo \"UUID=43162a5a-f1b2-441f-9d51-433bea2e113c /mnt/4tb  ext4  defaults,noatime  0 0\" | sudo tee -a /etc/fstab\n    $ echo \"UUID=b9479cb5-b306-430b-998d-3d793aadfde6 /mnt/1tb  ext4  defaults,noatime  0 0\" | sudo tee -a /etc/fstab\n    $ sudo systemctl daemon-reolad\n\n    # mount 'em now\n    $ sudo mount -a\n\nExposing Mounts via Samba\n~~~~~~~~~~~~~~~~~~~~~~~~~\n\n::\n\n    sudo apt update -y\n    sudo apt install -y --no-install-recommends samba samba-common-bin\n\n    # configure drives\n    # $ sudo vi /etc/samba/smb.conf\n    # # For a readonly drive:\n    # [pi-1tb]\n    #   path = /mnt/1tb\n    #   browseable = yes\n    #   writeable = no\n    #   guest ok = yes\n    # # Or, to allow writes:\n    # [pi-4tb]\n    #   path = /mnt/4tb\n    #   browseable = yes\n    #   writeable = yes\n    #   guest ok = yes\n    #   public = yes\n    #   create mask = 6444\n    #   directory mask = 0755\n    #   force user = pi\n    #   force group = pi\n\n    # create a samba user\n    # eg. username is \"pi\"\n    sudo smbpasswd -a pi\n\n    # restart samba\n    sudo systemctl restart smbd\n\nConnect to Samba Shares\n~~~~~~~~~~~~~~~~~~~~~~~\n\nTo mount samba shares on OSX clients, note that the permissions the server\ngrants and the permissions OSX *thinks* it has don't tend to stay in sync very\nwell. The best thing I've found to deal with this so far is to force OSX to\nthink it has 0777 -- it won't, the real permissions will be controlled by the\nsamba settings above as they are for all other clients, but at least OSX won't\nget in the way.\n\n::\n\n    # ./bin/osx-samba-mount HOSTNAME MOUNTNAME\n    ./bin/osx-samba-mount pi-1 pi-1tb\n    ./bin/osx-samba-mount pi-1 pi-4tb\n\nTo connect on Windows, use File Explorer, right-click \"This PC\" and \"Add a\nNetwork Drive\". Then input \"\\\\IP.ADDR\\SHARE_NAME\". You may need to input the\ncredentials: \"guest:\".\n\nTODOs\n-----\n\n* use syncthing folder to hold migratable state?\n* deploy `bar assistant \u003chttps://github.com/karlomikus/bar-assistant\u003e`_\n* deploy `a recipe tracker \u003chttps://github.com/awesome-selfhosted/awesome-selfhosted#recipe-management\u003e`_, perhaps alongside a shopping list\n* deploy `an html render of my vimwiki \u003chttps://github.com/vimwiki/vimwiki#changing-wiki-syntax\u003e`_\n* n8n automations:\n  * sync work and home gcal\n* configure `voice control \u003chttps://rhasspy.readthedocs.io/en/latest/\u003e`_\n* deploy a `feed reader \u003chttps://github.com/awesome-selfhosted/awesome-selfhosted#feed-readers\u003e`_\n* backup photos from Google:\n  * consider adding a tagger such as `digikam \u003chttps://www.digikam.org/\u003e`_ to embed metadata\n  * consider a simple frontend (photoprism is way too much)\n* configure `notifications \u003chttps://github.com/caronc/apprise\u003e`_\n* monitor:\n  * `hard drives \u003chttps://github.com/AnalogJ/scrutiny\u003e`_\n  * and \"everything else\" via prometheus/grafana\n* manage `music \u003chttps://lidarr.audio/\u003e`_\n* optimize `transcoding of tv shows and movies \u003chttps://home.tdarr.io/\u003e`_\n* selfhost `location sharing \u003chttps://github.com/bilde2910/Hauk\u003e`_\n* investigate `openhab hub as new aio dashboard \u003chttps://www.openhab.org/\u003e`_\n* set up `chatbot \u003chttps://errbot.readthedocs.io/en/latest/\u003e`_\n* selfhost `calendars and contacts \u003chttps://github.com/awesome-selfhosted/awesome-selfhosted#calendar--contacts---caldav-or-carddav-servers\u003e`_, backup from Google\n* host calendar scheduling:\n  * `cal.com \u003chttps://cal.com/\u003e`_\n  * `easyappointments \u003chttps://github.com/alextselegidis/easyappointments\u003e`_\n* backup my bookmarks:\n  * `various options \u003chttps://github.com/awesome-selfhosted/awesome-selfhosted#bookmarks-and-link-sharing\u003e`_\n  * `lnks \u003chttps://github.com/hamvocke/lnks\u003e`_\n  * `sync from firefox \u003chttps://floccus.org/\u003e`_\n* mirror repos to `gitea \u003chttps://about.gitea.com/\u003e`_:\n  * check out `plugins \u003chttps://gitea.com/gitea/awesome-gitea\u003e`_\n  * also `mirror to gitlab \u003chttps://docs.gitlab.com/ee/user/project/repository/mirror/index.html\u003e`_?\n  * also mirror to sourcehut?\n  * `mirroring script \u003chttps://github.com/beefsack/git-mirror\u003e`_\n\n.. _set up networking: https://wiki.debian.org/NetworkConfiguration\n.. _Debian: https://www.debian.org/releases/stable/installmanual\n.. _Raspbian OS Lite x64: https://www.raspberrypi.com/software/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthekevjames%2Fselfhost","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthekevjames%2Fselfhost","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthekevjames%2Fselfhost/lists"}