Skip to content
Gitea install copy/pasta instructions for FreeNAS and FreeBSD iocage jails.
Branch: master
Clone or download
Latest commit d614ee5 Nov 24, 2018
Type Name Latest commit message Commit time
Failed to load latest commit information.
LICENSE Updated LICENSE to BSD 3 Feb 9, 2018 Update Nov 19, 2018

FreeNAS-Gitea v2.0

v2.0 for 2018.

This is no longer a fully automated script, but more a set of instructions & copy/paste code. The previous version is in the gogs:

Eventually this should be an iocage plugin when there is good documentation on how to do that *cough*cough*.

Changes & Improvements

Here be dragons

One should never just blindly copy and paste oneliners from the internet into shells, especially root shells. It's I take issue with PiHole and other projects' installation instructions.

The code snippets aren't overly complex and are a great way to learn about FreeBSD and shell scripting. There are also some environmental valiables that need changed for your home network.


  • Everything should be run as root or prefix with sudo.
  • Instructions are written for bash shell in the FreeNAS environment, tcsh for the jail environment.
cd /tmp/; sudo bash

1. Create iocage jail.

# Jail Configuration
# Change this for your network.

# Remove any existing jail by that name.
iocage destroy --force ${NAME}
# Create a new jail.
iocage create --basejail --release=${RELEASE} --name=${NAME}
# Setup networking.
iocage set ip4_addr=${IP4_ADDR} ${NAME}

2. Initial Jail Setup.

Start the jail, so that it's running:

iocage start ${NAME}

Install required packages.

PACKAGES='nginx-lite mysql57-server gitea redis'
iocage pkg ${NAME} install --yes ${PACKAGES}

2. Services Setup

I am by no means a mysql, redis, gitea or nginx admin. These are mostly the FreeBSD defaults. This machine not exposed to the internet.

Contributions & constructive feedback are welcome.

To begin, drop into a shell on the jail. The rest of the commands are to be executed inside of the jail.

iocage console ${NAME}


Configure Redis:

setenv CFG /usr/local/etc/redis.conf
cp ${CFG}.sample ${CFG}
: Enable unix socket.
sed -i .bak -e 's/# unixsocket/unixsocket/g' ${CFG}
: Change permissions so git user can use it
sed -i .bak -e 's/unixsocketperm 700/unixsocketperm 777/g' ${CFG}
: Disable TCP.
sed -i .bak -e 's/^port 6379/port 0/' ${CFG}
diff ${CFG} ${CFG}.sample

Enable & Start Redis:

: Enable redis.
sysrc redis_enable=yes
: Start redis.
service redis start

Check that it's started:

cat /var/log/redis/redis.log

Should have this line:

* The server is now ready to accept connections at /tmp/redis.sock


Configure MySQL and disable networking.

setenv CFG /usr/local/etc/mysql/my.cnf
cp ${CFG}.sample ${CFG}
sed -i .bak -e 's/^\[mysqld\]$/[mysqld]\\
skip-networking/' ${CFG}
diff ${CFG} ${CFG}.sample

Enable & Start MySQL

sysrc mysql_enable=yes
sysrc mysql_args=--skip-networking
service mysql-server start

Secure MySQL installation.

  • Follow the prompts.
  • If you don't change the root password, it's in /root/.mysql_secret


Verify you can connect and login:

mysql --socket=/tmp/mysql.sock -u root -p

For whatever reason, you have to reset the password again through ALTER USER. You can reuse the same password.

ALTER USER 'root'@'localhost' IDENTIFIED BY '...';

Create the gitea database and exit mysql client.

CREATE DATABASE `gitea` DEFAULT CHARACTER SET `utf8mb4` COLLATE `utf8mb4_unicode_ci`;


Configure SSH:

  • Only allow git
  • Disable password login
setenv CFG /etc/ssh/sshd_config

cat <<EOF> ${CFG}
AllowUsers git
ChallengeResponseAuthentication no
PasswordAuthentication no
UsePAM no 

Enable & Start SSH Server.

sysrc sshd_enable=yes
service sshd start


Configure Gitea:

  • Enable lage file support.
  • Configure DB to use MySQL
  • Configure HTTP to listen on a socket.
  • Configure session backend to use redis.
  • Configure cache backend to use redis.
  • Allow attachments.
  • Configure secrets.
  • Disable gravatars, captcha & http git.

For more information on Gitea configuration settings see the Gitea Configuration Cheat Sheet.

: Generate some random secret strings.
setenv LFS_JWT_SECRET `cat /dev/urandom | tr -dc 'a-zA-Z0-9_' | fold -w 43 | head -n 1`
setenv SECRET_KEY `cat /dev/urandom | tr -dc 'a-zA-Z0-9_' | fold -w 43 | head -n 1`

setenv CFG /usr/local/etc/gitea/conf/app.ini
cp ${CFG}.sample ${CFG}

: Setup Gitea database
sed -i .bak -e "s/DB_TYPE  = sqlite3/DB_TYPE  = mysql/" ${CFG}
sed -i .bak -e "s/HOST     =     = \/tmp\/mysql.sock/" ${CFG}
sed -i .bak -e "s/PATH     = \/var\/db\/gitea\/gitea.db/PATH     =/" ${CFG}
: Setup Gitea server
sed -i .bak -e 's/^\[server\]$/[server]\\
LFS_CONTENT_PATH = \/var\/db\/gitea\/data\/lfs \\
PROTOCOL     = unix/' ${CFG}
sed -i .bak -e "s/HTTP_ADDR    =    = \/tmp\/gitea.sock/" ${CFG}
sed -i .bak -e "s/HTTP_PORT    = 3000/HTTP_PORT    = /" ${CFG}
sed -i .bak -e "s/ROOT_URL     = http:\/\/localhost:3000/ROOT_URL     = https:\/\/%\(DOMAIN\)s/" ${CFG}
: Change the secret.
sed -i .bak -e "s/SECRET_KEY   = ChangeMeBeforeRunning/SECRET_KEY   = ${SECRET_KEY}/" ${CFG}
: Disable stuff.
sed -i .bak -e "s/DISABLE_GRAVATAR        = false/DISABLE_GRAVATAR        = true/" ${CFG}
sed -i .bak -e "s/ENABLE_CAPTCHA         = true/ENABLE_CAPTCHA         = false/" ${CFG}
sed -i .bak -e "s/DISABLE_HTTP_GIT = false/DISABLE_HTTP_GIT = true/" ${CFG}
: Configure session backend.
sed -i .bak -e "s/PROVIDER = file/PROVIDER = redis/" ${CFG}
sed -i .bak -e "s/PROVIDER_CONFIG = \/var\/db\/gitea\/data\/sessions/PROVIDER_CONFIG = network=unix,addr=\/tmp\/redis.sock,db=0,pool_size=100,idle_timeout=180/" ${CFG}
: Configure cache backend.
cat <<EOF>> ${CFG}
ADAPTER = redis
HOST = network=unix,addr=/tmp/redis.sock,db=1,pool_size=100,idle_timeout=180

ENABLED = true
PATH = /var/db/gitea/data/attachments
: Compare the files. Eyeball the results for a sanity check.
diff ${CFG} ${CFG}.sample

Open /usr/local/etc/gitea/conf/app.ini in your favorite editor.

  • Under [database]. Add the MySQL password. Wrap passwords with special characters in "`".
  • Under [server]. Change DOMAIN to the IP address of the jail.

Enable gitea & start it.

sysrc gitea_enable=yes
service gitea start

Wait a few seconds and check the log for errors:

cat /var/log/gitea/gitea.log

Optional Gitea/FreeNAS Integration.

By default gitea saves all of its data in /var/db/gitea with respect to the jail. So all of your data will have an actual path like this: /mnt/tank/iocage/jails/gitea_jail/root/var/db/gitea

You can use the iocage fstab command to mount a path from the jail host. This way your jails and data can live on different file systems.

Assuming your zpool is tank.

Stop the jail:

iocage stop gitea_jail

Create a ZFS filesystem:

zfs create tank/gitea

Fix permissions of the folder:

chown -R 211:211 /mnt/tank/gitea

Add an fstab entry

iocage fstab --add gitea_jail /mnt/tank/gitea /var/db/gitea nullfs defaults 0 0

Start the jail:

iocage start gitea_jail


Generate self signed SSL. Alternatively use Lets Encrypt, instructions left as an exercise to the reader.

Follow the prompts to generate a key & certificate:

openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /etc/ssl/nginx-selfsigned.key -out /etc/ssl/nginx-selfsigned.crt

Setup Nginx to:

  • Redirect all http requests to https.
  • Pass SSL requests on to the Gitea socket.
setenv CFG /usr/local/etc/nginx/nginx.conf
rm ${CFG}

cat <<EOM > ${CFG}
worker_processes  1;

events {
    worker_connections  1024;

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    server {
    	listen 80 default_server;
    	server_name _;
    	return 301 https://\$host\$request_uri;

    server {
        listen 443 ssl default_server;
    	server_name _;
    	ssl_certificate /etc/ssl/nginx-selfsigned.crt;
        ssl_certificate_key /etc/ssl/nginx-selfsigned.key;
        location / {
            proxy_pass http://unix:/tmp/gitea.sock;

Enable & Start Nginx:

sysrc nginx_enable=yes
service nginx start

Setup Gitea

Navigate to the IP address of your jail, in this example:

You should get an SSL warning "Your connection is not private/secure". Ignore it.

  • Setup your user.
  • Login as your user.
  • Use Gitea.

To clone a repository over https with a self signed certificate:

git -c http.sslVerify=false clone https://...

Or just use SSH.

Corrections & Issues

Testing the full set of instructions gets tedious after a while. If you find something doesn't work, open an issue:

If you know how to correct the issue, create a pull request with the fixes.

You can’t perform that action at this time.