Deployment docs for our Gogs server on Fly.io: https://gogs-server.fly.dev
We use GitHub as the
single source of truth
for our Product & Services. ⭐
Occasionally GitHub has
"incidents"
where it's offline for hours ... ⏳
Also, GitHub can
lose data
if you're not careful;
i.e. delete is forever! 🤦♀
So we needed an easy way to backup our data. 💾
Gogs is a lightweight Git server
with a familiar UI/UX
(think GitHub circa 2018 clone)
that can be deployed in 5 minutes
and has most of the GitHub features we use.
e.g:
Orgs, Repos, Markdown editor/viewer, Issues & Pull Requests.
Fly is a dramatically simplified Platform as a Service (PaaS) with an underlying easily accessible Infrastructure as a Service (IaaS). It combines the best elements of AWS and many from Heroku but focusses on the essential and eliminates the bloat. We love it and recommend it to anyone tired of the complexity of AWS or the cost of Heroku.
As the tagline says: "PostgreSQL: The World's Most Advanced Open Source Relational Database."
We use and love it because it's fast, has excellent docs and great tooling.
Note: We've used MySQL or MariaDB in the past they are both good. We think Postgres is better. It's the default Database for
Phoenixour chosen Web Framework, so using it with ourGogsserver makes sense to reduce cognitive load and cost.
This repository documents our deployment of our Gogs server.
See: https://gogs-server.fly.dev/
This is a step-by-step guide for recreating our server. If you find it useful, please ⭐
Create a Fly.io App for the Gogs Server:
flyctl launch --name gogs-server --image gogs/gogs --org dwylIn our case we called our app
gogs-server, pretty self-explanatory and not very creative. We like it when DevOps is immediately obvious. It dramatically reduces cognitive overload and context switching costs!
Select the type of instance you want:
? Select configuration: [Use arrows to move, type to filter]
> Development - Single node, 1x shared CPU, 256MB RAM, 1GB disk
Development - Single node, 1x shared CPU, 512MB RAM, 10GB disk
Production - Highly available, 1x shared CPU, 256MB RAM, 10GB disk
Production - Highly available, 1x Dedicated CPU, 2GB RAM, 50GB disk
Production - Highly available, 2x Dedicated CPU's, 4GB RAM, 100GB diskWe went with Development for now,
but once we have everything setup
we will return and create a Production instance.
Create a Volume (Network Attached Storage): https://fly.io/docs/reference/volumes/
fly volumes create data --region lhrThe volume is called data.
But under-the-hood the fly system
gives it a unique name.
You can easily check this if needed by running:
The default size is 10Gb. We definitely won't need that much.
If you already have a Postgres database cluster on Fly, you can host as many Postgres databases on as you like, the resources are scaled up automatically.
"Users won't notice this! They’re directed to the nearest running instance automatically."
Just remember to enable autoscaling on your DB cluster (see below).
Create a DB named gogs-server-db in the lhr (London) region:
fly pg create --name gogs-server-db --region lhrUse your preferred region.
see: https://fly.io/docs/reference/scaling/
fly autoscale standard min=1Attach the DB to the Gogs server:
fly postgres attach --app gogs-server --postgres-app gogs-server-dbWhen you first visit your Gogs instance,
you will be redirected to the /install page.
These were the settings we defined on ours:
If you make a mistake with the setup of your Gogs server,
don't panic, you can easily update
the
app.ini
file to change any of the settings.
Login to the VM via ssh:
flyctl ssh consoleTrack down the app.ini file on the instance:
find / -name app.iniIn my case it was at:
/data/gogs/conf/app.iniBefore making any changes,
make a backup of the file
in case you need to revert.
e.g:
gogs-server/main/app.ini
Edit/update it:
vi /data/gogs/conf/app.iniI updated:
SSH_PORT = 22To
SSH_PORT = 10022This mirrors the port forwarding defined in the fly.toml file:
fly.toml#L52
If you make any changes to the app.ini file,
you will need to restart the VM that is running your gogs instance.
e.g:
flyctl restart gogs-serverYou will see output confirming the restart:
gogs-server is being restartedMake sure to have START_SSH_SERVER to false in your app.ini file:
START_SSH_SERVER = falseIf defined to true you might not be able to add ssh keys via the Gogs
setting UI automatically.
You will need to rewrite the file manualy by runing the admin command:

see: gogs/gogs#4751
https://gogs-server.fly.dev/nelsonic
I created a couple of repos, one public the other private to test.
Next we want to interact with a repo ...
Add your ssh key to the Gogs instance
so that you can interact with the repo via git
in your terminal.
Copy the public ssh key on your main computer.
In my case the id_rsa.pub file is located at
~/.ssh/id_rsa.pub
on my Mac.
So to copy the contents of the file,
I run the following command:
pbcopy < ~/.ssh/id_rsa.pubNext, connect to the Gogs Server
and visit the /user/settings/ssh
page, e.g:
https://gogs-server.fly.dev/user/settings/ssh
Once you've successfully added your public ssh key
to Gogs you should see a success message such as:
Create a repository if you don't already have one, e.g: https://gogs-server.fly.dev/nelsonic/public-repo
If you attempt to clone the repo using a standard command, e.g:
git clone git@gogs-server.fly.dev:nelsonic/public-repo.gitYou will see the following error:
ssh: connect to host gogs-server.fly.dev port 22: Connection refused
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.This is because the TCP port 22 is reserved
for actual SSH connections on Fly.io.
We could re-assign it for use with Gogs,
but then we would lose the ability to ssh into the instance ...
We don't want that,
because it's useful to fly ssh console
to debug & maintain the instance.
Attempt to specify the TCP port:
git clone -p 10022 git@gogs-server.fly.dev:nelsonic/public-repo.gitThat doesn't work. So reading: https://stackoverflow.com/questions/5767850/git-on-custom-ssh-port
Trying the following format: https://stackoverflow.com/a/5767880/1148249
git clone ssh://git@mydomain.com:[port]/org|usernam/repo-name.gite.g:
git clone ssh://git@gogs-server.fly.dev:10022/nelsonic/public-repo.gitUpdate the README.md on my Mac:
git commit and git push the code:
git push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 350 bytes | 350.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
To ssh://gogs-server.fly.dev:10022/nelsonic/public-repo.git
7f92c5d..f714a64 master -> masterhttps://gogs-server.fly.dev/nelsonic/public-repo

Here is the content on the draft branch:

git clone ssh://git@gogs-server.fly.dev:10022/nelsonic/private-repo.gitEdit the README.md:
git add . && git commit -m 'updated on mac' && git pushOutput:
1 file changed, 3 insertions(+), 1 deletion(-)
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 341 bytes | 341.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
To ssh://gogs-server.fly.dev:10022/nelsonic/private-repo.git
5977268..c5d8552 master -> masterResult: https://gogs-server.fly.dev/nelsonic/private-repo
Though you'll just have to take our word for it because the repo is `private ...
You will see a 404 error if you attempt to visit the URL.
The second way of connecting to Gogs is via the REST API.
Here we will be following and expanding on the official docs:
https://github.com/gogs/docs-api
Visit: /user/settings/applications of your Gogs instance,
e.g:
https://gogs-server.fly.dev/user/settings/applications
And click on Generate New Token.
Then input the name of your token, in case you end up with multiple tokens.
Token generated:
My access token is:
0ed304c9921c2cf33da4c832f843c160b70bb97e.
We will be using this below. Make a note of yours.
Don't worry, this token was deleted immediately after we confirmed that everything was working while writing this guide (
beforepublishing it!) so no risk in making this example public.
With this access token in-hand we can now run
cURL
commands
to test the REST API, e.g:
curl -u "nelsonic" 'https://gogs-server.fly.dev/api/v1/users/unknwon/tokens'You will be prompted for the password for your username on gogs
Response:
[{"name":"API Test","sha1":"0ed304c9921c2cf33da4c832f843c160b70bb97e"}]%The same as the token above.
Now let's test accessing a repo via the REST API:
curl 'https://gogs-server.fly.dev/api/v1/repos/nelsonic/public-repo?token=0ed304c9921c2cf33da4c832f843c160b70bb97e'{
"id": 1,
"owner": {
"id": 1,
"username": "nelsonic",
"login": "nelsonic",
"full_name": "",
"email": "nelson@dwyl.com",
"avatar_url": "https://secure.gravatar.com/avatar/f937427bea8db9d88608a54b2b803f1a?d=identicon"
},
"name": "public-repo",
"full_name": "nelsonic/public-repo",
"description": "testing public repo on gogs server running on fly.io",
"private": false,
"fork": false,
"parent": null,
"empty": false,
"mirror": false,
"size": 61440,
"html_url": "https://gogs-server.fly.dev/nelsonic/public-repo",
"ssh_url": "ssh://git@https://gogs-server.fly.dev:10022/nelsonic/public-repo.git",
"clone_url": "https://gogs-server.fly.dev/nelsonic/public-repo.git",
"website": "",
"stars_count": 0,
"forks_count": 0,
"watchers_count": 1,
"open_issues_count": 0,
"default_branch": "master",
"created_at": "2022-04-22T01:53:48Z",
"updated_at": "2022-04-22T01:53:48Z",
"permissions": {
"admin": true,
"push": true,
"pull": true
}
}Next we want to read the contents of the README.md of a repo,
the API path has the following pattern:
/api/v1/repos/:username/:reponame/raw/:ref/:pathExample:
curl 'https://gogs-server.fly.dev/api/v1/repos/nelsonic/public-repo/raw/master/README.md?token=0ed304c9921c2cf33da4c832f843c160b70bb97e'Response:
# public-repo
testing public repo on gogs server running on fly.io
Update on `README.md` Mac ... 🚀Exactly what we expect it to be. 🎉
REST API is working. ✅
As noted above, we removed the access token
from our Gogs server
before publishing this:
In a real-world app, API Key rotation is a good idea. see: https://cloud.google.com/kms/docs/key-rotation
- Fly CLI: https://fly.io/docs/flyctl/
- Fly Launch: https://fly.io/docs/flyctl/launch/
- Fly Deploy: https://fly.io/docs/flyctl/deploy/
- App Configuration (fly.toml): https://fly.io/docs/reference/configuration/
- Appkata: Gogs - standalone Git Server (Fly.io)
https://fly.io/docs/app-guides/git-gogs-server/
Note: this is a bit old (2020)
and there is no longer a
fly initcommand and thefly.tomlfile is incomplete. Hence us needing to write these docs. Thanks given to @codepope in: https://community.fly.io/t/gogs-standalone-git-service-as-a-fly-example/358/2 - Multi-region PostgreSQL: https://fly.io/docs/getting-started/multi-region-databases/
- Scaling and Autoscaling https://fly.io/docs/reference/scaling/
- Autoscale: https://fly.io/docs/flyctl/autoscale/
- Auto-scaling tutorial: https://hosting.analythium.io/auto-scaling-shiny-apps-in-multiple-regions-with-fly-io/
- SSH troubleshooting: https://docs.github.com/en/authentication/troubleshooting-ssh/using-ssh-over-the-https-port














