Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save josephbadow/588c2ae961231fe338c459127c7d835b to your computer and use it in GitHub Desktop.
Save josephbadow/588c2ae961231fe338c459127c7d835b to your computer and use it in GitHub Desktop.
Install Firefly on a Raspberry Pi 3 with Docker, Docker Compose and a self-signed certificate

I'm running a dockerized Firefly III on a Raspberry 3 in my local network. With the help of an additional nginx Container and a self-signed SSL Certificate I was able to set up https.

Maybe somebody will find this guide helpfull, it took me a couple of tries to get it right.

Install Docker on the Raspberry

Simply follow the official documentation at https://docs.docker.com/install/linux/docker-ce/debian/#install-using-the-convenience-script. You'll need to run the script if you are using the default Raspberry OS: Raspbian.

Install Docker Compose using Python PIP

Use Pythons package manager PIP to install Docker Compose, details can be found on docker.com as well: https://docs.docker.com/compose/install/#install-using-pip. Before you can follow the guide you'll need to install python-pip.

sudo apt-get install python3-pip

Test Firefly III with Docker Compose

Follow the official Guide at https://firefly-iii.readthedocs.io/en/latest/installation/docker.html#docker-hub-with-automatic-updates-via-docker-compose to install Firefly III on your Pi and test if you can access it at http://hostname-of-pi. You can check your host name with hostname and modify it with sudo raspi-config. Mine is called raspberry01 and therefore I access it via http://raspberry01.

Generate a new SSL certificate

With openssl you can easily create the required SSL certificate. The certificate will be valid for 365 days.

openssl req -x509 -newkey rsa:2048 -keyout raspberry01.key -out raspberry01.crt -days 365 -nodes

Creating the key on the Raspberry might take a moment. You will be asked for additional information that will be parsed into the certificate but the only important one is the Common Name. You should enter the hostname of your Raspberry here. The others can be skipped with return.

Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:raspberry01
Email Address []:

The command created two files (raspberry01.key, raspberry01.crt) that we need to copy to our docker environment.

Further explanation and options to create a certificate can be read about in this stackoverflow post: https://stackoverflow.com/questions/10175812/how-to-create-a-self-signed-certificate-with-openssl.

Prepare nginx configuration

Next to my /opt/docker/firefly/docker-compose.yml file I created a new folder conf.d. I moved the newly created certificate and key to this folder and created a new configuration file (raspberry01.conf) for nginx.

server {
  listen 80; 
  #redirect all http traffic to https
  return 301 https://$host$request_uri;
}

server {
  listen 443 ssl;
  ssl_certificate /etc/nginx/conf.d/raspberry01.crt;
  ssl_certificate_key /etc/nginx/conf.d/raspberry01.key;
  location / {
    proxy_pass http://172.24.0.1:80;
    proxy_set_header        Host                    $host;
    proxy_set_header        X-Real-IP               $remote_addr;
    proxy_set_header        X-Forwarded-For         $proxy_add_x_forwarded_for;
    proxy_set_header        X-Forwarded-Host        $server_name;
    proxy_set_header        X-Forwarded-Proto       $scheme;
    proxy_set_header        X-Forwarded-Ssl         on;
    proxy_set_header        Upgrade                 $http_upgrade;
    proxy_set_header        Connection              "upgrade";
  }
}

The proxy_pass IP is the Gateway address of my Firefly Docker network. You can check yours by running

docker network inspect firefly_firefly_iii_net

I copied the proxy_set_header options from another issue (#2579) and cannot say if all of them are relevant.

Now you should have a somewhat similar file and folder structure:

    |-- /opt/docker/firefly
        |-- docker-compose.yml
        |-- conf.d
            |-- raspberry01.conf
            |-- raspberry01.crt
            |-- raspberry01.key

Modify docker-compose.yml and .env files

I added the official nginx image as additional service to the docker-compose.yml file. Adding it to the existing firefly_iii_net network, exposing port 443 and mounting the local folder conf.d read-only into the container.

[...]
  nginx_proxy:
    image: nginx:latest
    networks:
      - firefly_iii_net
    ports:
      - "443:443"
    volumes:
      - /opt/docker/firefly/conf.d:/etc/nginx/conf.d:ro
[...]

In the .env file you need to set APP_URL and TRUSTED_PROXIES.

[...]
# This variable must match your installation's external address but keep in mind that
# it's only used on the command line as a fallback value.
APP_URL=https://raspberry01

# TRUSTED_PROXIES is a useful variable when using Docker and/or a reverse proxy.
# Set it to ** and reverse proxies work just fine.
TRUSTED_PROXIES=**
[...]

(Re)start your containers and access your Firefly App via https

docker-compose -f /opt/docker/firefly/docker-compse.yml up -d

The first start will download the newly added nginx image which will delay everything for a moment. Access https://hostname-of-pi and accept the browser warning. You created the certificate yourself, it was not signed by an official certificate authority, therefore you are warned by the browser.

@maiqueg
Copy link

maiqueg commented Jan 16, 2020

Hi,
I am new at linux and trying to follow this tutorial. However I have gotten stuck at (Generate a new SSL certificate) step. I am not sure how nginx fits into to this.
Questions:

1. Are there additional steps for setting up nginx?

2. The command: "docker network inspect firefly_firefly_iii_net" gives me an error: "Error: no such network: firefly_firefly_iii_net" not sure what this means

3. Would you outline the steps in more detail for a complete novice like me. My apologies for asking for so much hand holding. For example it is not clear to me exactly where in the docker-compose.yml file I should add:

nginx_proxy:
image: nginx:latest
networks:

  • firefly_iii_net
    ports:
  • "443:443"
    volumes:
  • /opt/docker/firefly/conf.d:/etc/nginx/conf.d:ro

and what the volumes: line should look like for me on my Pi setup.

Thank you!

  1. No
  2. You can use the command "docker network ls" to show the available network names. Grab the one that have "firefly" on it and use the inspect command as described above.
  3. You need to add it at the line with the containers, Nginx will be another one. You'll end with 3 containers running, one for the Firefly app, another for the database and the third with Nginx.

Example:

--- 
networks: 
  firefly_iii_net: 
    driver: bridge
services: 
  firefly_iii_app: 
    image: jc5x/firefly-iii:latest
    depends_on:
      - firefly_iii_db
    networks: 
      - firefly_iii_net
    ports: 
      - "80:80"
    env_file: .env
    volumes: 
      - 
        source: firefly_iii_export
        target: /var/www/firefly-iii/storage/export
        type: volume
      - 
        source: firefly_iii_upload
        target: /var/www/firefly-iii/storage/upload
        type: volume
  firefly_iii_db: 
    image: "postgres:10"
    environment:
      - POSTGRES_PASSWORD=secret_firefly_password
      - POSTGRES_USER=firefly
    networks: 
      - firefly_iii_net
    volumes: 
      - firefly_iii_db:/var/lib/postgresql/data
  nginx_proxy:
    image: nginx:latest
    networks:
      - firefly_iii_net
    ports:
      - "443:443"
    volumes:
      - /opt/docker/firefly/conf.d:/etc/nginx/conf.d:ro
version: "3.2"
volumes: 
  firefly_iii_db: ~
  firefly_iii_export: ~
  firefly_iii_upload: ~

I've followed the above tutorial, it works but there are a few adjustments to be made.

Nginx won't handle the redirect from port 80 to 443, since by default the container firefly_iii_app runs an Apache within port 80. So I ended with this docker-compose.yml:

--- 
networks: 
  firefly_iii_net: 
    driver: bridge
services: 
  firefly_iii_app: 
    image: jc5x/firefly-iii:latest
    depends_on:
      - firefly_iii_db
    networks: 
      - firefly_iii_net
    env_file: .env
    volumes: 
      - 
        source: firefly_iii_export
        target: /var/www/firefly-iii/storage/export
        type: volume
      - 
        source: firefly_iii_upload
        target: /var/www/firefly-iii/storage/upload
        type: volume
  firefly_iii_db: 
    image: "postgres:10"
    environment:
      - POSTGRES_PASSWORD=secret_firefly_password
      - POSTGRES_USER=firefly
    networks: 
      - firefly_iii_net
    volumes: 
      - firefly_iii_db:/var/lib/postgresql/data
  nginx_proxy:
    image: nginx:latest
    networks:
      - firefly_iii_net
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /opt/docker/firefly/conf.d:/etc/nginx/conf.d:ro
version: "3.2"
volumes: 
  firefly_iii_db: ~
  firefly_iii_export: ~
  firefly_iii_upload: ~
  • Removed the port 80 from being exposed on firefly_iii_app and added it to nginx_proxy.
  • Instead of using the IP of the network gateway on the "proxy_pass", I used the IP of the firefly_iii_app. (You can find out the IP of each container using the command already used above "docker network inspect firefly_firefly_iii_net")

@bonehead
Copy link

bonehead commented Apr 1, 2020

Hi,

The link https://firefly-iii.readthedocs.io/en/latest/installation/docker.html#docker-hub-with-automatic-updates-via-docker-compose isn't working, could you please help with an alternative if possible.

@maiqueg
Copy link

maiqueg commented Apr 1, 2020

Hi,

The link https://firefly-iii.readthedocs.io/en/latest/installation/docker.html#docker-hub-with-automatic-updates-via-docker-compose isn't working, could you please help with an alternative if possible.

Hello.

Yes, the url to the documentation changed, you can find it here:
https://docs.firefly-iii.org/installation/docker

@nebula2
Copy link

nebula2 commented Apr 28, 2020

Hey @josephbadow,
just wanted to thank you for this. it saved me a lot of time :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment