This ended up to be an intermediate guide that requires you to understand linux, the differences between embedded and server (or desktop) systems, some of how router firmwares work. This can surely consume up to a few hours of your day.
It is important that you understand your architecture. The AC88U Router I used in this example is an armv7l.
uname -m
armv7l
Unless you use an armv7, this guide may not be 100% applicable to you, so expect changes for amd64, armv5, armv6. For other architectures such as mips, you may need to build gogs, or run into not being supported.
Read this for GoLang: https://github.com/golang/go/wiki/MinimumRequirements Gogs tends to run on all architectures Go supports.
Note: this may in large part be applicable to gitea (https://docs.gitea.io/en-us/) too.
You should be all set when you are reading this, but to recap, all we need here is a working DDWRT installation, a disk (yeah a spinning old-school HDD. I would advise against using NAND/flash memory/SDCard/Pendrive) in and entware fully functioning.
There are multiple packages available in entware, but note that your router will come with emulated FPU/HW FPU unavailable. Package you need therefore is not the normal go, but go_nohf (No Hard Float) instead.
opkg install go_nohf
Installing go_nohf (1.12.5-1) to root...
Downloading http://bin.entware.net/armv7sf-k3.2/go_nohf_1.12.5-1_armv7-3.2.ipk
Configuring go_nohf.
Please add /opt/bin/go/bin to your PATH
Please set GOROOT=/opt/bin/go environment variable to use GO compiler
After this, add the set GOROOT, GOPATH and add these to your path.
if [ -d /opt/bin/go ]; then export GOROOT=/opt/bin/go; export GOPATH=$HOME/srcs/go; export PATH=$PATH:$GOROOT/bin; fi
Add this to be configured at boot time for your user, e.g. your /tmp/root/.profile should have this. The easiest way to achieve this is to add the above line to your startup commands:
echo "if [ -d /opt/bin/go ]; then export GOROOT=/opt/bin/go; export GOPATH=/opt/home/go; export PATH=$PATH:$GOROOT/bin; fi" >> /tmp/root/.profile
Don't forget to:
mkdir -p /opt/home/go
Now the reason we do this is to avoid having this in /tmp/root as that can vanish easily (like after every router power cut/reboot). At this point, go should run just fine, give it a go:
> go version
go version go1.12.5 linux/arm
For HTTPS magic you will need a few packages to establish your cert store.
opkg install ca-bundle ca-certificates
Listing that /opt/etc/ssl/certs directory should contain a bunch of certificates at this point. Now export that SSL dir, as we're gonna need that in future:
export SSL_CERT_DIR='/opt/etc/ssl/certs'
PS: you can add your own custom RootCAs here too - but that's another trick. So you may want to add this export for your user at boot time: add to startup commands:
echo "export SSL_CERT_DIR='/opt/etc/ssl/certs'" >> /tmp/root/.profile
Some more SSL magic here: https://github.com/Neilpang/acme.sh/wiki/How-to-run-on-DD-WRT-with-lighttpd (this actually runs the ddwrt UI for you under your own RootCAs)
Use the git-http package as that allows you to fetch from http and https too. And test.
opkg install git-http
git --version
git version 2.21.0
I'll be using MariaDB (MySQL) for this installation, but note that gogs supports posgresql and sqlite too. For MySQL to work though, you will need to get a working swap in place. Note though that it is a very bad idea to install SWAP on NAND (remember that I recommended using a HDD above? here it comes again: use a HDD).
Install these:
opkg install mariadb-client mariadb-server
Check if you have mkswap and swapon utils available on your ddwrt edition:
which mkswap
/sbin/mkswap
which swapon
/sbin/swapon
In case you don't see these packages install swap-utils with opkg.
Creating a 1GB swap on your disk would be:
dd if=/dev/zero of=/tmp/mnt/sda1/swap bs=1024k count=1000
mkswap /tmp/mnt/sda1/swap
Now check free:
free
total used free shared buff/cache available
Mem: 514568 91836 72908 0 349824 307376
Turn on your swap and check free again:
swapon -p1 /tmp/mnt/sda1/swap
free
total used free shared buff/cache available
Mem: 514568 91836 72908 0 349824 307376
Swap: 1023996 176 1023820
And you may want to add this to a attach at boot time (e.g. startup commands):
# add this to startup commands:
if [ -f '/tmp/mnt/sda1/swap' ]; then swapon -p1 /tmp/mnt/sda1/swap; fi
More swap magic here: https://wiki.dd-wrt.com/wiki/index.php/Linux_SWAP
Now onto the MySQL configs - you'll need /opt/etc/mysql/conf.d/50-server.cnf first. Modify the datadir and tmpdir, make sure you use a HDD. Also, this router in particular doesn't support Native AIO, and we don't need the server to keep reminding us, let's turn that off too.
# /opt/etc/mysql/conf.d/50-server.cnf
datadir = /tmp/mnt/sda1/mysql
tmpdir = /tmp/mnt/sda1/tmp/mysql
innodb_use_native_aio = 0
Now get data init:
mysql_install_db --force
Some problems can be resolved by ln -s /opt/etc/mysql/my.cnf ~/.my.cnf (https://forum.dd-wrt.com/phpBB2/viewtopic.php?p=931282) This should run without any problems now, and mysql should run at the end of the process. Do the usual magic as you would do with mysql elsewhere: set a root pass, configure to match memory limits, etc.
Now I haven't been able to find a gogs build that was working fine on ddwrt (binaries are built on Pi for armv7 I think, and libs are diff / elsewhere); so I ended up building from source.
Note: given the alternate caching options, it can be OK to keep GOGS running from NAND, and have the data piece sitting on the HDD.
go get -u -tags "cert" github.com/gogs/gogs
Now you can customize the tags, above is using "cert" only, but you can go with -tags "cert sqlite pam" whatever you need.
At present, the following tags are available:
- sqlite: SQLite3 database support
- pam: PAM authentication support
- cert: Generate self-signed certificates support
- miniwinsvc: Builtin windows service support (or you can use NSSM to create a service)
This may change tho, so keep an eye out to: https://golang.org/pkg/go/build/#hdr-Build_Constraints
Should you have built gogs previously, you may notice the /gogs/gogs instead of /gogits/gogs. That is intentional, repo name has changed (and thus many of the guides out there are out of date currently; like this will be in a years time lol).
So this may take about 2-3 minutes to complete.
Let's build:
cd $GOPATH/src/github.com/gogs/gogs
go build -tags "cert"
Building with cert takes about a minute on this router. You can tell this was successful when you have a gogs binary available in the same directory, and it actually returns some info:
$GOPATH/src/github.com/gogs/gogs/gogs --help
NAME:
Gogs - A painless self-hosted Git service
USAGE:
gogs [global options] command [command options] [arguments...]
VERSION:
0.11.91.0811
COMMANDS:
web Start web server
serv This command should only be called by SSH shell
hook Delegate commands to corresponding Git hooks
cert Generate self-signed certificate
admin Perform admin operations on command line
import Import portable data as local Gogs data
backup Backup files and database
restore Restore files and database from backup
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--help, -h show help
--version, -v print the version
This page will have the latest: https://gogs.io/docs/installation/install_from_binary. Grab that tar.gz and tar -zxvf it into $GOPATH/srcs/go/github.com/gogits/, so you end up with a $GOPATH/src/github.com/gogs/gogs directory with about 47MB of content.
Try running the $GOPATH/src/github.com/gogs/gogs/gogs binary with --help to see that it's working fine.
Let's create a database first and grant privs. Note that I'm using zpz2ecPn3gxPuxhkPxEdppGJCkbvGE7g as the user and ZvDTdomLrpMk77tZe9quZKcNxg9bem6PRcpQDNPA93W95ahncAq5hg5qYy5GLkKy as the password in this example - you may want to change those.
mysql -u root -p
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 8
Server version: 10.2.24-MariaDB Source distribution
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> CREATE DATABASE IF NOT EXISTS gogs_0_11_91;
Query OK, 1 row affected (0.39 sec)
MariaDB [(none)]> GRANT ALL ON gogs_0_11_91.* TO zpz2ecPn3gxPuxhkPxEdppGJCkbvGE7g@localhost IDENTIFIED BY 'ZvDTdomLrpMk77tZe9quZKcNxg9bem6PRcpQDNPA93W95ahncAq5hg5qYy5GLkKy';
Query OK, 0 rows affected (0.49 sec)
MariaDB [(none)]> quit;
Bye
You'll find the default configuration saved in $GOPATH/src/github.com/gogs/gogs/conf/app.ini It's recommended to leave that untouched and come up with a custom config:
cd $GOPATH/src/github.com/gogs/gogs
mkdir -p custom/conf
cp conf/app.ini custom/conf/app.ini
Decide where you repos are going to be. I placed them on HDD, but a low-fequency git is also OK on NAND (the DB and caching will take the heavy load here). I ended up with something like /tmp/mnt/sda1/data.gogs
And now open it in your favorite editor, and make several changes. Look into these for now:
- APP_NAME whatever domain you host this on - should make sense though as certs would need to match this in their CN.
- RUN_USER given a few quirks, you are only allowed to run this as root (see securing your install section in case you're not happy with this).
- SSH_PORT defaults to 22, you may want to change this, or the one you set for ddwrt.
- DATA is your app data (e.g. attachments and stuff will end up here, can consume space if you let it down below), I've set it to be in my gogs data dir on the HDD /tmp/mnt/sda1/data.gogs/data
- ROOT is your repo root, in my case it will be /tmp/mnt/sda1/data.gogs/repos
- DB_TYPE = mysql (unless you are using something else)
- HOST = 127.0.0.1:3306 (or incase you're using socket: /var/run/mysqld/mysqld.sock or wherever your socket file is at)
- NAME = gogs_0_11_91 (or whatever else you set)
- USER = zpz2ecPn3gxPuxhkPxEdppGJCkbvGE7g or whatever you set this to
- PASSWD = ZvDTdomLrpMk77tZe9quZKcNxg9bem6PRcpQDNPA93W95ahncAq5hg5qYy5GLkKy or whatever you set this to
- SECRET_KEY = yes, change this to something bad like 9pGojnQZbqRhzYUKB2yg74qi5SrVyn3fWTQKrYKnqS5dGyjHA9PNU8WjypWj4gUR
- MODE under log is one to look at: keep it as "console", or create a logging directory on your HDD (this can be intensive wear for NAND).
This is a dry run, so we don't worry about certificates for now :)
More on configs on gogs pages: https://gogs.io/docs/installation/configuration_and_run The most interesting piece will be https://gogs.io/docs/advanced/configuration_cheat_sheet
Test your drive like:
cd $GOPATH/src/github.com/gogs/gogs
./gogs web
Opening your http://gogsdomain:3000 should show you gogs for advanced configuration.
There is a few things around this.
So you may not keep this running as "root", but at the same time, the users your router provides (like "nobody") may be insufficient to proceed with.
Installing shadown on a ddwrt router can be difficult, but here goes my logic:
So think this: you can get gogs to run as "nobody" and that is fine. On the other hand, when you want to use a non-root SSH to push and pull and fetch and what not, you may need something else. Like shadow, the first step towards real unix users and groups. Stop and make that decision here.
WARNING WARNING WARNING It is easy to lock yourself out this way. You may want to create an nvram backup and be prepared to reset your router to factory default should it come to that.
Packages needed:
opkg install shadow-common shadow-groups shadow-nologin
Installing shadow-common (4.6-1) to root...
Downloading http://bin.entware.net/armv7sf-k3.2/shadow-common_4.6-1_armv7-3.2.ipk
Installing shadow-groups (4.6-1) to root...
Downloading http://bin.entware.net/armv7sf-k3.2/shadow-groups_4.6-1_armv7-3.2.ipk
Installing shadow-nologin (4.6-1) to root...
Downloading http://bin.entware.net/armv7sf-k3.2/shadow-nologin_4.6-1_armv7-3.2.ipk
Configuring shadow-common.
Configuring shadow-nologin.
Configuring shadow-groups.
This gets you /opt/etc/passwd and /opt/etc/group.
A bunch you may need until you're setup and ready to go (these can be removed after settings & config and done, and used only when they're really required).
opkg install shadow-groupadd shadow-groupdel shadow-useradd shadow-userdel
Installing shadow-groupadd (4.6-1) to root...
Downloading http://bin.entware.net/armv7sf-k3.2/shadow-groupadd_4.6-1_armv7-3.2.ipk
Installing shadow-groupdel (4.6-1) to root...
Downloading http://bin.entware.net/armv7sf-k3.2/shadow-groupdel_4.6-1_armv7-3.2.ipk
Installing shadow-useradd (4.6-1) to root...
Downloading http://bin.entware.net/armv7sf-k3.2/shadow-useradd_4.6-1_armv7-3.2.ipk
Installing shadow-userdel (4.6-1) to root...
Downloading http://bin.entware.net/armv7sf-k3.2/shadow-userdel_4.6-1_armv7-3.2.ipk
Configuring shadow-useradd.
Configuring shadow-groupadd.
Configuring shadow-userdel.
Configuring shadow-groupdel.
After this initial setup, we end up with /opt/etc/passwd.1 and /opt/etc/group.1 as backups, and symlinks pointing from /opt/etc to /etc:
/opt/etc/passwd -> /etc/passwd
/opt/etc/group -> /etc/group
For our purpose, we need to turn this around, so go ahead and remove those symlinks and copy them over physically:
rm /opt/etc/passwd
cp /etc/passwd /opt/etc
rm /opt/etc/group
cp /etc/group /opt/etc
Now let's make sure we have the users and groups defaulted to what ddwrt has. Unless we bindmount these to /etc/passwd and /etc/group, they are not much use, but note: we need the current users (and these may change depending on ddwrt build, or even after an update should that decision be made).
To migitage this risk, I ended up with a small script called shadow-update.sh that merges passwd and group contents from /etc to /opt/etc, and bindmounts it back to /etc, so we can default to that.
Test this separately without adding to boot first (that way you can recover easily with a reboot).
#!/bin/bash
###
### update users from /etc/passwd to /etc/opt/passwd so we follow system wide user / pwd changes.
###
function update_shadow {
# validate and reassign var
if [[ "$1" == "" || "$2" == "" ]]; then return 1; else n="$2"; fi
# iterate through our original content ($1)
for o in `echo "$1" |sed 's#:.*##'`; do
# get each individual line from our original content ($1)
upln=`echo "$1" |grep ^$o`
# update these lines in the alternate content ($2)
n=`echo "$n" |sed "s#^$o.*#$upln#"`
done
}
# get pwd updated and when update is successful, write new file and bindmount to override.
n=""; opwd=`cat /etc/passwd` && npwd=`cat /opt/etc/passwd` && update_shadow "$opwd" "$npwd"
if [[ "$n" != "" ]]; then echo "$n" > /opt/etc/passwd && umount /etc/passwd > /dev/null 2>&1; mount --bind /opt/etc/passwd /etc/passwd && passwd_status="Successful" || passwd_status="Failed"; fi
# get grp updated and when update is successful, write new file and bindmount to override.
n=""; ogrp=`cat /etc/group` && ngrp=`cat /opt/etc/group` && update_shadow "$ogrp" "$ngrp"
if [[ "$n" != "" ]]; then echo "$n" > /opt/etc/group && umount /etc/group > /dev/null 2>&1; mount --bind /opt/etc/group /etc/group && group_status="Successful" || group_status="Failed"; fi
So let's test this, look into /etc/passwd and /opt/etc/passwd after creating a user and set it a nice long password (we need this for ssh later on):
useradd gogs -s /bin/bash -M -d /tmp/mnt/sda1/data.gogs/home
passwd gogs
Changing password for gogs
Enter the new password (minimum of 5, maximum of 8 characters)
Please use a combination of upper and lower case letters and numbers.
New password:
Re-enter new password:
passwd: password changed.
cat /etc/passwd
root:$blahblah:0:0:Root User,,,:/tmp/root:/bin/sh
reboot:$blahblah:0:0:Root User,,,:/tmp/root:/sbin/reboot
nobody:x:99:99:Nobody:/:/bin/false
crontabs:*:0:0:Contab User,,,:/var:/bin/false
zabbix:*:65533:65533:zabbix:/var:/bin/false
cat /opt/etc/passwd
root:$blahblah:0:0:Root User,,,:/tmp/root:/bin/sh
reboot:$blahblah:0:0:Root User,,,:/tmp/root:/sbin/reboot
nobody:x:99:99:Nobody:/:/bin/false
crontabs:*:0:0:Contab User,,,:/var:/bin/false
zabbix:*:65533:65533:zabbix:/var:/bin/false
gogs:/blahblah:1000:1000::/tmp/mnt/sda1/data.gogs/home:/bin/false
We see what we expect: gogs user is not in /etc/passwd, but is in /opt/etc/passwd. Now run that script above, and validate the results:
/opt/bin/shadow-update.sh
cat /etc/passwd
root:$blahblah:0:0:Root User,,,:/tmp/root:/bin/sh
reboot:$blahblah:0:0:Root User,,,:/tmp/root:/sbin/reboot
nobody:x:99:99:Nobody:/:/bin/false
crontabs:*:0:0:Contab User,,,:/var:/bin/false
zabbix:*:65533:65533:zabbix:/var:/bin/false
gogs:/blahblah:1000:1000::/tmp/mnt/sda1/data.gogs/home:/bin/false
So sone this is set, you can run gogs with a gogs user, and make all data ownership dedicated to that folk. At this point, you may also want to consider making further changes to your system. More users and dedicated service users is a generally good starting point - pretty much all router firmwares tend to run everything as root for simplicity.
Make config changes:
RUN_USER = gogs
Note, that after changing the run user, you will need to amend some permissions too. Remember, my data dir was /tmp/mnt/sda1/data.gogs
chown -R gogs:gogs /tmp/mnt/sda1/data.gogs
Also, at this point, we can set this to be: owned by gogs, can read and execute by anyone in the gogs group, but everybody else can go grab a beer:
find /tmp/mnt/sda1/data.gogs -type d -exec chmod 750 {} \;
find /tmp/mnt/sda1/data.gogs -type f -exec chmod 640 {} \;
Give your changes a "go" to see if any errors are turned up to be fixed, before we proceed:
sudo -u gogs ./gogs web
2019/08/18 14:41:24 [TRACE] Custom path: /opt/go/src/github.com/gogs/gogs/custom
2019/08/18 14:41:24 [TRACE] Log path: /tmp/mnt/sda1/data.gogs/logs
2019/08/18 14:41:24 [ INFO] gogs.mb 0.11.91.0811
2019/08/18 14:41:24 [ INFO] Cache Service Enabled
2019/08/18 14:41:24 [ INFO] Session Service Enabled
2019/08/18 14:41:25 [ INFO] Git Version: 2.21.0
2019/08/18 14:41:25 [ INFO] Run Mode: Production
Now in case you selected to use the internal SSH server, you will see an error saying [FATAL] Fail to start SSH server: listen tcp 0.0.0.0:22: bind: permission denied. That is because non-root user will not be allowed to bind, unless set with setcap (part of libcap on linux), but we don't have that option from entware. That leaves us with two ways: a) build libcap from source (likely a bit overkill for the purpose b) use dropbear as that's the default, c) install openssh.
I went with option c) given I'd like to maintain the ability to restrict those services with separate rules, so here goes.
Easy go:
opkg install openssh-server
Downloading http://bin.entware.net/armv7sf-k3.2/openssh-server_8.0p1-1_armv7-3.2.ipk
Configuring openssh-server.
Make config changes in /opt/etc/ssh/sshd_config
- PermitRootLogin no
- #HostKey /opt/etc/ssh/ssh_host_ecdsa_key - comment these out, RSA is enough
- #HostKey /opt/etc/ssh/ssh_host_ed25519_key - comment these out, RSA is enough
You will also need to create a user for privilige separation called sshd, and you will need to update shadow (shadow-update.sh script is somewhere above). And test that /etc/passwd has it correctly.
useradd sshd -s /bin/false -M -d /opt/var/empty
/opt/bin/shadow-update.sh
cat /etc/passwd |grep ^sshd
sshd:!:1001:1001::/opt/var/empty:/bin/false
You need to generate an RSA host key too:
ssh-keygen -t rsa -b 4096 -f /opt/etc/ssh/ssh_host_rsa_key
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /opt/etc/ssh/ssh_host_rsa_key.
Your public key has been saved in /opt/etc/ssh/ssh_host_rsa_key.pub.
The key fingerprint is:
SHA256:blahblah root@myhost
The key's randomart image is:
+---[RSA 4096]----+
...
+----[SHA256]-----+
At this point, your SSH server should be OK to start up. Test it too:
/opt/etc/init.d/S40sshd start
starting sshd...
netstat -apn |grep sshd
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 12409/sshd
Make the following modifications in your $GOPATH/src/github.com/gogs/gogs/custom/conf/app.ini:
- START_SSH_SERVER set to false.
Also, please make sure you have absolute paths at all places where files are written, so we can individually ensure permissions are all correct: ssh root
- SSH_ROOT_PATH = /tmp/mnt/sda1/data.gogs/home
app data
- APP_DATA_PATH = /tmp/mnt/sda1/data.gogs/data
repos root
- ROOT = /tmp/mnt/sda1/data.gogs/repos
temp uploads
- TEMP_PATH = /tmp/mnt/sda1/data.gogs/data/tmp/uploads
attachemnts
- PATH = /tmp/mnt/sda1/data.gogs/data/attachments
sqlite
- PATH = /tmp/mnt/sda1/data.gogs/data/gogs.db
avatars and repo avatars:
- PROVIDER_CONFIG = /tmp/mnt/sda1/data.gogs/data/avatars
- AVATAR_UPLOAD_PATH = /tmp/mnt/sda1/data.gogs/data/avatars repo avatars:
- REPOSITORY_AVATAR_UPLOAD_PATH = /tmp/mnt/sda1/data.gogs/data/repo-avatars attachments:
- PATH = /tmp/mnt/sda1/data.gogs/data/attachments logs:
- ROOT_PATH = /tmp/mnt/sda1/data.gogs/logs
Try starting gogs:
cd $GOPATH/src/github.com/gogs/gogs/
sudo -u gogs ./gogs web
The following example was submitted for gogs / develop branch as gogs/gogs#5795 This is taking rc.func default functions and extends it with the magic we need for gogs, and will avoid calling it after launch. Usual gogs start/stop/check will work just fine.
Note: you will need sudo and daemonize present from opkg.
#!/bin/sh
### Custom user script for gogs
### First param is:
### "start" (call at start entware),
### "stop" (call before stop entware),
###
### Note the additional requirements for gogs on ddwrt: shadow user, group, sudo, daemonize
PIDFILE="/opt/var/run/gogs.pid"
USER="gogs"
GOROOT="/opt/bin/go"
GOPATH="/opt/go"
ENABLED=yes
PROC="gogs"
DESC=$PROC
PREARGS="/opt/bin/sudo -u $USER /opt/bin/daemonize"
GOGSBIN="$GOPATH/src/github.com/gogs/gogs/gogs"
ARGS="web"
ansi_red="\033[1;31m";
ansi_white="\033[1;37m";
ansi_green="\033[1;32m";
ansi_yellow="\033[1;33m";
ansi_blue="\033[1;34m";
ansi_bell="\007";
ansi_blink="\033[5m";
ansi_std="\033[m";
ansi_rev="\033[7m";
ansi_ul="\033[4m";
case "$1" in
start)
# start gogs web
if [ -f "$PIDFILE" ]
then
echo "$DESC is already running ...`pidof $PROC`"
else
echo -e -n "$ansi_white Starting $DESC... $ansi_std"
export GOROOT=$GOROOT
export GOPATH=$GOPATH
export PATH=$PATH:$GOROOT/bin
$PREARGS $GOGSBIN $ARGS > /dev/null 2>&1 &
COUNTER=0
LIMIT=10
while [ -z "`pidof $PROC`" -a "$COUNTER" -le "$LIMIT" ]; do
sleep 1;
COUNTER=`expr $COUNTER + 1`
done
if [ -z "`pidof $PROC`" ]
then
echo -e " $ansi_red failed. $ansi_std"
logger "Failed to start $DESC from $CALLER."
return 255
else
echo -e " $ansi_green done. $ansi_std"
logger "Started $DESC from $CALLER."
echo `pidof $PROC` > "$PIDFILE"
return 0
fi
fi
;;
stop)
echo -e -n "$ansi_white Shutting down $PROC... $ansi_std"
killall $PROC 2>/dev/null
if [ -f "$PIDFILE" ]
then
rm "$PIDFILE"
fi
COUNTER=0
LIMIT=10
while [ -n "`pidof $PROC`" -a "$COUNTER" -le "$LIMIT" ]; do
sleep 1;
COUNTER=`expr $COUNTER + 1`
done
;;
kill)
echo -e -n "$ansi_white Killing $PROC... $ansi_std"
killall -9 $PROC 2>/dev/null
;;
status | check)
echo -e -n "$ansi_white Checking $DESC... "
if [ -n "`pidof $PROC`" ]
then
echo -e " $ansi_green alive. $ansi_std";
return 0
else
echo -e " $ansi_red dead. $ansi_std";
return 1
fi
;;
*)
echo "Usage: $0 {start|stop|status}"
exit 1
;;
esac
Change all of these:
- COOKIE_USERNAME - something that isn't the default
- COOKIE_REMEMBER_NAME - something that isn't the default
- COOKIE_SECURE - true maybe? :)
- OFFLINE_MODE - set to true in case you want to limit exposure (will disable gravatar :( )
So applying SSL to gogs directly didn't look like a good idea to me, so I ended up adding an Nginx reverse proxy, and limiting gogs' http service to localhost. Not getting into much details here, this is what my site.enabled.conf has:
server {
listen 80;
server_name gogs.lan git.lan github.lan source.lan src.lan sources.lan code.lan repo.lan repos.lan;
return 301 https://gogs.lan$request_uri;
location / {
try_files $uri $uri/ =404;
add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
if_modified_since off;
expires off;
etag off;
}
}
server {
listen 443 ssl;
server_name gogs.lan;
ssl_certificate /opt/myssl/host_gogs.lan.crt;
ssl_certificate_key /opt/myssl/host_gogs.lan.key;
ssl_dhparam /opt/myssl/host_gogs.lan.dhparam.2048.pem;
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 10s;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'AESGCM:HIGH:!aNULL:!MD5';
# performance tuning
gzip off;
client_max_body_size 128M;
# static error pages
error_page 401 /401.html; error_page 402 /402.html; error_page 403 /403.html; error_page 404 /404.html;
error_page 500 /500.html;
# static files caching, don't log to accesslog
location ~* ^/(/.+\.(jpg|jpeg|gif|bmp|ico|png|css|js|swf|pdf))$ { expires 30d; access_log off; }
# deny a bunch of files we don't need to access via nginx ever.
location ~ ^/(?:\.htaccess|data|config|db_structure\.xml|README) { deny all; }
location / {
allow from 192.168.0.0; # lol, example
deny all;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://localhost:3000;
}
}
And at the same time, limit access to gogs and update domains properly in your $GOPATH/src/github.com/gogs/gogs/custom/conf/app.ini
- PROTOCOL = http
- DOMAIN = gogs.lan
- ROOT_URL = https://gogs.lan/
- HTTP_ADDR = 127.0.0.1
- HTTP_PORT = 3000
By this, you're limiting http address to 127.0.0.1 (which is OK as gogs.lan and https://gogs.lan will be used). When restarting gogs with this config, you should have no access to gogs.lan on port 3000 anymore.
Gogs listen on 3000 that you can allow in. You may also decide to limit that option if you're running the nginx proxy, you won't be connecting to 3000 directly under normal circumstances.
This is based on https://blog.meinside.dev/Gogs-on-Raspberry-Pi/ but obvs changes had to be made as of DDWRT.