Mastodon

Setup GoToSocial on AWS Lightsail

That will be a short microblog-style post. As you may know AWS Community Builder, as part of the program benefits is receiving 500$ per year of AWS Cloud credits. Seems a lot, however, domain name registration is excluded, also based on on-demand pricing, 500$ is ok for test ideas, or writing content. Not very good, for long-running services different from S3. However, some time ago I thought about running software on VMs. Not inside containers just as binary. So, why not to use Lightsail? It's simple, even too simple. Thankfully it has, a stable low price, especially if we decide to go with IPv6.

Lightsail

Build applications and websites Fast with low-cost, pre-configured cloud resources

The problem with Lightsail is the level of simplicity. You have fewer options, than with the usage of EC2. You can just sping your instance, choose keys, basic firewall, assign tags and that's is more-less all. Don't believe me? Check Terraform module.

Is that good? In some cases yes. Setting simple 5$/month machine, with centOS-stream, and Ipv4 (for setup time only) it's possible tyle lini kodu, and looks like that:

 1terraform {
 2  required_version = ">= 1.12.1"
 3  required_providers {
 4    aws = {
 5      source  = "hashicorp/aws"
 6      version = "5.94.1"
 7    }
 8  }
 9}
10
11provider "aws" {
12  region = "eu-central-1"
13}
14
15resource "aws_lightsail_instance" "gotosocial-instnace" {
16  name              = "my-great-app"
17  availability_zone = "eu-central-1a"
18  blueprint_id      = "centos_stream_9" #  aws lightsail get-blueprints | jq ".blueprints[].blueprintId"
19  bundle_id         = "micro_3_0"       #  aws lightsail get-bundles
20
21  # regular aws_key_pair is not supported here
22  # also needs to be just RSA, ed25519 is not accepted
23  user_data = <<-EOF
24    #!/bin/bash
25    mkdir /home/ec2-user/.ssh
26    echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJxYZEBNRLXmuign6ZgNbmaSK7cnQAgFpx8cCscoqVed local" > /home/ec2-user/.ssh/authorized_keys
27    chmod 0700 /home/ec2-user/.ssh
28    chmod 0600 /home/ec2-user/.ssh/authorized_keys
29    chown -R ec2-user:ec2-user /home/ec2-user/.ssh
30    dnf update -y
31  EOF
32
33  tags = {
34    Environment = "Development"
35    Project     = "GoToSocial"
36  }
37}
38
39resource "aws_lightsail_instance_public_ports" "open-22" {
40  instance_name = aws_lightsail_instance.gotosocial-instnace.name
41
42  port_info {
43    protocol  = "tcp"
44    from_port = 22
45    to_port   = 22
46  }
47}
48
49output "ipv4-ip" {
50  value = aws_lightsail_instance.gotosocial-instnace.public_ip_address
51}

As you can see some comments, let's discuss them.

  1. We can find the correct blueprint with aws lightsail get-blueprints --query "blueprints[].blueprintId". Important note is that we can deploy not only fresh OS but sets like WordPress, or drupal.
  2. Then in the case of size, we have bundles, different than in the case of EC2.
  3. user-data. Due issues with adding keys, supported format, etc, I prefer putting them directly.
  4. The only needed port for now is tcp/22 for SSH.

Good! After running tf init && tf apply --auto-approve, we're getting fresh IPv4's IP address.

To log in we need:

1ssh [email protected] -i ~/.ssh/id_ed25519_local

Please note, that as long as we have open port 22, we can use SSM, to establish a connection from the Terminal/WebUI level.

Tailscale

But, hey! We would like to use IPv6, mostly for reducing costs. The problem is that most ISPs (or at least Orange in Poland) do not support IPv6, so using agent-based VPN. Just simplify our setup a lot!

How to install the agent on Linux VM? Very simple. In most cases just:

1sudo dnf config-manager --add-repo https://pkgs.tailscale.com/stable/centos/9/tailscale.repo
2sudo dnf install tailscale
3sudo systemctl enable --now tailscaled
4sudo tailscale up

Then based on your Tailnet config, you need to accept it, copy your IP , and bum:

1ssh [email protected] -i ~/.ssh/id_ed25519_local
2Last login: Wed May 28 11:36:04 2025 from 100.116.167.109
3[ec2-user@ip-172-26-11-7 ~]$

Ok, at this point we can just delete resource "aws_lightsail_instance_public_ports" "open-22" { block from our Terraform manifest, and re-apply config.

Cloudflare

The next topic is access to our instance from outside. Based on my self-hosting experience, using Cloudflare Tunnels are just the easiest possible way of hosting apps in a small environment, without taking care about setting nginx on our own.

Basically what to do?

  1. Install cloudflared.

  2. Click tunnel panel

    Zero trust view, choose tunnel under networking
  3. Click Create a tunnel

    New tunnel view, creation of new tunnel
  4. Use Cloudflared as tunnel type

    Tunnel type view
  5. Add the name of the tunnel

    Tunnel creator view
  6. Copy configuration part(especially token) on side

    Service install tab
  7. Configure your tunnel (finally)

    1. Use a subdomain for your tunnel, for example, social.
    2. Choose a domain in my case jakubwolynko.eu.
    3. The service is related to your app, it could be HTTP.
    4. URL, so in case of binary deployment classic - localhost:<port>
    Tunnel configuration view

At this point we have all prerequisites installed to install our app on Lightsail. It's not necessary to use GoToSocial, it could be almost anything you will find on this list.

GoToSocial

Ok, stop. What is GoToSocial?

GoToSocial is an ActivityPub social network server, written in Golang. GoToSocial provides a lightweight, customizable, and safety-focused entryway into the Fediverse. With GoToSocial, you can keep in touch with your friends, post, read, and share images and articles. All without being tracked or advertised to!

Still not clear? So it's your instance of the so-called Fediverse. Think about it as on your own Twitter sever, where you are an Elon, It's just empty, and not federated - yet.

Installation

We can just over the docs. here.

So steps will be:

  1. Directory creation

    1sudo mkdir /gotosocial && cd /gotosocial
    
  2. Getting the recent package

    1GTS_VERSION=X.Y.Z # Replace this
    2GTS_TARGET=linux_amd64
    3wget https://codeberg.org/superseriousbusiness/gotosocial/releases/download/v${GTS_VERSION}/gotosocial_${GTS_VERSION}_${GTS_TARGET}.tar.gz
    
  3. Extract it

    1tar -xzf gotosocial_${GTS_VERSION}_${GTS_TARGET}.tar.gz
    
  4. Creation of gotosocial.service file

    1wget https://codeberg.org/superseriousbusiness/gotosocial/raw/branch/main/example/gotosocial.service -O gotosocial.service
    
  5. Copy systemd service

    1sudo cp gotosocial.service /etc/systemd/system/
    
  6. User management

    1sudo useradd -r gotosocial
    2sudo groupadd gotosocial
    3sudo usermod -a -G gotosocial gotosocial
    4sudo chown -R gotosocial:gotosocial /gotosocial
    
  7. Insert base configuration into config.yaml

    Note, that I'm using port 8080, just to avoid unnecessary permission for gotosocial user.

    1host: social.jakubwolynko.eu
    2port: 8080
    3storage-local-base-path: /gotosocial/storage
    4db-type: "sqlite"
    5db-address: "sqlite.db"
    6
    7instance-languages: ["pl", "en"]
    
  8. Enable and start service

    1sudo systemctl enable --now gotosocial.service
    2sudo systemctl start gotosocial.service
    

At this point, our service is running. The last step is to expose it via the Cloudflare tunnel. Do you remember the step, when we copied our service install command? Now we need it.

  1. Install cloudflared service.

    1sudo cloudflared service install eyJhIjoiZ...
    

Now as long, as we're on Ipv4 it's all good. Unfortunately at some point, we would like to change it. That is why we need one small tweak in /etc/systemd/system/cloudflared.service.

1# FROM
2ExecStart=/usr/bin/cloudflared tunnel run --token eyJhIjoiZ...
3
4# INTO
5
6ExecStart=/usr/bin/cloudflared --edge-ip-version 6 tunnel run --token eyJhIjoiZ...

Big test

Now we need to go into AWS Console and change our network options from IPv4 to IPv6.

  1. Change network type

    General Instance view
  2. Choose IPv6-only and confirm all steps

    Select Network Type view

Ok, after that let's check our SSH connection over Tailscale, as well as our application access over Cloudflare.

1$ curl -s https://social.jakubwolynko.eu/ | grep About
2                    <h3 id="about">About this instance</h3>
3                            About social.jakubwolynko.eu

Summary

And here we are, with setting instance for 5$, or even 3.5$, covered entirely via the AWS Community Program. That is nice, not only for GoToSocial, but also for miniflux, N8N, or anything, you could self-host, but EC2 was too expensive, for personal usage.

Additional note, I'm not using GoToSocial anymore. Seems like having empty instances, and content based on connected folks' action/reaction is just too little for me. That's why I decided to use hachyderm.io.

So, host your own stuff fellows Community Builders!

And to code is here at codeberg.org.