I'm playing with self hosting Mastodon. Setup is not trivial, and everybody has special requirements. Common guides do this:
As for my requirements: I have a VM, where I run an nginx as frontend/reverse proxy, and then I run services like Lychee-picture hosting in podman containers. I want to run Mastodon in a single podman container. Mastodon does like the other services just plain http, and the nginx as frontend does the https encapsulation. Following steps are for this setup.
I use a Debian bookworm system which is a KVM guest at a provider. I run systemd in the Debian container, for easy execution of the Mastodon services like Postgresql.
mkdir -p ~/mastodon/build-bookworm cd mastodon cat >build-bookworm/Containerfile<<EOT FROM docker.io/library/debian:bookworm ENV DEBIAN_FRONTEND noninteractive EXPOSE 80 RUN apt update && apt upgrade -y && \ apt install -y curl wget gnupg apt-transport-https \ lsb-release ca-certificates sudo systemd procps CMD [ "/lib/systemd/systemd" ] EOT # build locally podman build -t mastodon build-bookworm/ # run locally podman run -p 127.0.0.1:8084:80 --name mastodon -d \ --security-opt seccomp=unconfined \ localhost/mastodon /lib/systemd/systemd # get a shell podman exec -it mastodon bash
## install nodejs 16 ## https://github.com/nodesource/distributions#installation-instructions mkdir -p /etc/apt/keyrings curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | \ gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_16.x nodistro main" | \ tee /etc/apt/sources.list.d/nodesource.list apt update apt install -y nodejs #### postgresql repo wget -nv -O /usr/share/keyrings/postgresql.asc https://www.postgresql.org/media/keys/ACCC4CF8.asc echo "deb [signed-by=/usr/share/keyrings/postgresql.asc] http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/postgresql.list #### system packages apt update apt install -y \ imagemagick ffmpeg libpq-dev libxml2-dev libxslt1-dev file git-core \ g++ libprotobuf-dev protobuf-compiler pkg-config nodejs gcc autoconf \ bison build-essential libssl-dev libyaml-dev libreadline6-dev \ zlib1g-dev libncurses5-dev libffi-dev libgdbm-dev nvi \ nginx redis-server redis-tools postgresql postgresql-contrib \ certbot python3-certbot-nginx libidn11-dev libicu-dev libjemalloc-dev systemctl start redis postgresql sudo -u postgres psql CREATE USER mastodon CREATEDB; alter user mastodon with password 'mypasswordhere'; \q #### yarn/corepack apt install -y npm npm install -g corepack corepack enable yarn set version classic adduser --disabled-login mastodon usermod -s /bin/bash mastodon su - mastodon git clone https://github.com/rbenv/rbenv.git ~/.rbenv cd ~/.rbenv && src/configure && make -C src echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc echo 'eval "$(rbenv init -)"' >> ~/.bashrc echo "alias ll='ls -al'" >> ~/.bashrc exec bash git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install 3.2.3 rbenv global 3.2.3 gem install bundler --no-document cd /home/mastodon git clone https://github.com/mastodon/mastodon.git live && cd live # git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1) git tag -l | grep -v 'rc[0-9]*$' | sort -V git checkout v4.2.1 bundle config deployment 'true' bundle config without 'development test' bundle install -j$(getconf _NPROCESSORS_ONLN) yarn install --pure-lockfile RAILS_ENV=production bundle exec rake mastodon:setup # https://docs.joinmastodon.org/admin/config/ PostgreSQL host: localhost PostgreSQL port: 5432 Name of PostgreSQL database: mastodon_production Name of PostgreSQL user: mastodon Password of PostgreSQL user: mypasswordhere Redis host: localhost Redis port, password: accept defaults # empty white page, but mastodon favicon # journalctl -u mastodon-web # https://github.com/mastodon/mastodon/issues/10926 RAILS_ENV=production bundle exec rails assets:clobber RAILS_ENV=production bundle exec rails assets:precompile exit # special nginx config so mastodon works with tcp/80: # https://blog.vyvojari.dev/mastodon-behind-a-reverse-proxy-without-ssl-https/ cp /home/mastodon/live/dist/nginx.conf /etc/nginx/sites-available/mastodon ln -s /etc/nginx/sites-available/mastodon /etc/nginx/sites-enabled/mastodon chmod go+rx /home/mastodon/ systemctl start nginx cp /home/mastodon/live/dist/mastodon-*.service /etc/systemd/system/ systemctl start mastodon-sidekiq mastodon-streaming mastodon-web
After that, deploy an nginx config on the host:
cat >/etc/nginx/sites-available/social<<EOT server { listen 443 http2; listen [::]:443 http2; server_name social.fluxcoil.net; access_log /opt/web/logs/social_access.log geoip; access_log /opt/web/logs/social_access_combined.log combined; error_log /opt/web/logs/social_error.log warn; keepalive_timeout 70; sendfile on; client_max_body_size 80m; location / { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Proxy ""; proxy_pass http://127.0.0.1:8084/; break; } } EOT systemctl restart nginx
With that, you should be able to log in with the browser.
podman exec -it mastodon bash apt update apt dist-upgrade su - mastodon cd /home/mastodon/live git fetch --tags git tag -l git checkout v4.2.8 bundle config deployment 'true' bundle config without 'development test' bundle install -j$(getconf _NPROCESSORS_ONLN) yarn install --pure-lockfile RAILS_ENV=production bundle exec rails assets:clobber RAILS_ENV=production bundle exec rails assets:precompile exit systemctl restart redis postgresql nginx systemctl restart mastodon-sidekiq systemctl restart mastodon-web systemctl restart mastodon-streaming