Skip to content

dwyl/gogs-server

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

gogs-server-logo

Deployment docs for our Gogs server on Fly.io: https://gogs-server.fly.dev

Why Gogs?

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.

Why Fly.io?

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.

Why Postgres?

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 Phoenix our chosen Web Framework, so using it with our Gogs server makes sense to reduce cognitive load and cost.


What?

This repository documents our deployment of our Gogs server.

See: https://gogs-server.fly.dev/

How?

This is a step-by-step guide for recreating our server. If you find it useful, please ⭐

Create an App

Create a Fly.io App for the Gogs Server:

flyctl launch --name gogs-server --image gogs/gogs --org dwyl

In 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 disk

We went with Development for now, but once we have everything setup we will return and create a Production instance.

Create a Volume

Create a Volume (Network Attached Storage): https://fly.io/docs/reference/volumes/

fly volumes create data --region lhr

The 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.



Quick Note on Fly.io Postgres Database Clusters

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 PostgreSQL DB & Attach to Gogs

Create a DB named gogs-server-db in the lhr (London) region:

fly pg create --name gogs-server-db --region lhr

Use your preferred region.

Enable Autoscaling

see: https://fly.io/docs/reference/scaling/

fly autoscale standard min=1

Attach the DB to the Gogs App

Attach the DB to the Gogs server:

fly postgres attach --app gogs-server --postgres-app gogs-server-db

Intialize Gogs!

When you first visit your Gogs instance, you will be redirected to the /install page. These were the settings we defined on ours:

gogs-fly-config-1of-2

gogs-fly-config-2of-2

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 console

Track down the app.ini file on the instance:

find / -name app.ini

In my case it was at:

/data/gogs/conf/app.ini

Before 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.ini

I updated:

SSH_PORT = 22

To

SSH_PORT = 10022

This 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-server

You will see output confirming the restart:

gogs-server is being restarted

Make sure to have START_SSH_SERVER to false in your app.ini file:

START_SSH_SERVER = false

If 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: image

see: gogs/gogs#4751

Test the Gogs Instance

https://gogs-server.fly.dev/nelsonic

image

I created a couple of repos, one public the other private to test.

Next we want to interact with a repo ...

Add SSH Key

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.pub

Next, 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:

image

Clone Repo

Create a repository if you don't already have one, e.g: https://gogs-server.fly.dev/nelsonic/public-repo

image

If you attempt to clone the repo using a standard command, e.g:

git clone git@gogs-server.fly.dev:nelsonic/public-repo.git

You 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.git

That 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.git

e.g:

git clone ssh://git@gogs-server.fly.dev:10022/nelsonic/public-repo.git

Make local changes

Update the README.md on my Mac:

image

Commit & Push Changes

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 -> master

Confirm they Worked!

https://gogs-server.fly.dev/nelsonic/public-repo image

Branches work: image

Here is the content on the draft branch: image

Check that it works for the private repo

git clone ssh://git@gogs-server.fly.dev:10022/nelsonic/private-repo.git

Edit the README.md:

image

git add . && git commit -m 'updated on mac' && git push

Output:

 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 -> master

Result: https://gogs-server.fly.dev/nelsonic/private-repo

private-repo-updated

Though you'll just have to take our word for it because the repo is `private ...

private-repo-404

You will see a 404 error if you attempt to visit the URL.



Connect via REST API (HTTPS)

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

gogs-gen-new-token

And click on Generate New Token.

Then input the name of your token, in case you end up with multiple tokens.

gogs-gen-token

Token generated:

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 (before publishing 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/:path

Example:

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. ✅

Delete the Token

As noted above, we removed the access token from our Gogs server before publishing this:

gogs-token-deleted

In a real-world app, API Key rotation is a good idea. see: https://cloud.google.com/kms/docs/key-rotation


Recommended Reading


HitCount