In my adventure to put some order in my personal photos library, and this new view of self-hosting as much as possible, I ended up installing a Nextcloud instance in my Raspberry Pi 4. It's about a month and a half since I've been playing around with it so I consider it stable enough to stay with me.
In this article I intend to log the actions to have it up and running
We're going to install Nextcloud on a Rasberry Pi 4 running Debian (or Raspbian, or the Raspberry OS as they call it now) using Docker:
I am basically following this article I found (thanx chrisbeardy, nice job!), but some things are not working the same for me and I had to fix some points in a different way (and that's why this article!)
I have some premises here that are important for me:
Even this section appears big, we "just" need a machine to install the Nextcloud, and DNS & internet access to our machine. Breaking this down in parts, what we need is:
I will use my Raspberry Pi 4 4GB to host it. It is not the most powerful one but it demonstrated to work pretty well for a single user / household use. I have installed the official Raspberry OS 64 bits Lite version (no desktop). The steps are the same that I explained in my past article Quick DNS server in a Raspberry Pi, but making sure that we're selecting the 64 bits Lite version. What do you want to have setup in your Raspberry Pi?
xavi
)tatooine
. If not, just replace the host name with your Raspberry's IP)You want to access to your Raspberry through the open internet, so you want to have a domain set up. In my case I simply reused a domain I already own and set up a subdomain that points to my home address. To go a bit deeper, I like to use the combination of:
Some ISPs have a firewall by default that automatically block requests to your ports, or even allow you just a small subset in a strange ports range. This is a problem as you won't be able to access to your Raspberry from the internet, and all functionality on the go is gone.
I live in Germany and (luckily) my ISP is 1&1 (I am so happy that I could get rid of Vodafone). 1&1 has a firewall that they can disconnect for you if you request it via email to support@1und1.de. For other ISPs you'll need to check it with them.
Some ISPs deliver to the customers routers that have lot of functionalities sliced down. In my case I own the router so I have full control of it and it's configuration.
Before we start, and assuming that you already have your Raspberry up and running, go to the router and forward the ports 80 and 443 to the Rasberry Pi's host.
SSH to the Rasberry
ssh xavi@tatooine
Download the Docker installer
curl -fsSL https://get.docker.com -o get-docker.sh
Install Docker
sh get-docker.sh
Add my current user (that's what $LOGNAME
refers to) into the docker
group
sudo usermod -aG docker $LOGNAME
Logout and SSH back again
Test that the docker is installed correctly by running a stupid container
docker container run hello-world
Get the ID of this container from the list of running containers
docker ps -a
Remove the container. We just wanted to test that it works:
docker rm ID_OF_HELLO_WORLD_CONTAINER
Visit the Docker website for more info.
This is not a required step, however portainer is a useful tool for setting up and managing docker containers so we are going to install this to make our lives easier to manage our containers later in the future.
Create a volume for the portainer's data
docker volume create portainer_data
Run a new container for portainer:
docker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce
Navigate to the portainer site to end up the configuration: http://tatooine:9000
Set up the admin username and password.
Select Docker
as the container environment to manage.
You'll be left into the portainer homepage of your instance. Visit their docs for more information.
We'll manage the containers by using docker-compose. Assuming that you're already SSHed into tatooine
:
sudo apt install docker-compose
We are going to use Nginx Proxy Manager for our reverse proxy, but as we are only running on a raspberry pi will setup using sqlite and not a full SQL database. Assuming that you're already SSHed into tatooine
:
Create a new proxy in Docker
docker network create proxy
We'll create all our services in our home. Move there.
cd ~
Create a directory for the proxy and move there
mkdir reverse-proxy
cd reverse-proxy
Create a docker-compose.yml file in this reverse-proxy
directory by editing a new file:
nano docker-compose.yml
Paste the following content:
version: "3"
networks:
proxy:
external: true
services:
reverse-proxy:
image: "jc21/nginx-proxy-manager:latest"
restart: always
ports:
- "80:80"
- "443:443"
- "81:81"
environment:
DB_SQLITE_FILE: "/data/database.sqlite"
DISABLE_IPV6: "true"
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
networks:
- proxy
Save the file (ctrl
+ o
) and exit (ctrl
+ x
)
Now create the container
docker-compose up -d
Navigate to the Proxy manager page: http://tatooine:81
Enter the following default credentials. You're requested to change them right after.
Email: admin@example.com
Password: changeme
Now comes the Nextcloud itself. One more time, assuming that you're already SSHed into tatooine
:
Move to the home directory where we settle all stacks:
cd ~
Create and move to a new nextcloud
directory
mkdir nextcloud
cd nextcloud
Create the conf.d
directory
mkdir conf.d
Create a docker-compose.yml file in this nextcloud
directory by editing a new file:
nano docker-compose.yml
Paste the following content:
version: '3'
volumes:
nextcloud-data:
nextcloud-db:
networks:
frontend:
external:
name: proxy
backend:
services:
nextcloud-app:
image: nextcloud
container_name: nextcloud
restart: always
volumes:
- nextcloud-data:/var/www/html
environment:
- MYSQL_PASSWORD=****
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_HOST=nextcloud-db
- PHP_UPLOAD_LIMIT=10G
- PHP_MEMORY_LIMIT=512M
networks:
- frontend
- backend
nextcloud-db:
image: mariadb
restart: always
command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW --innodb-file-per-table=1 --skip-innodb-read-only-compressed
volumes:
- nextcloud-db:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=****
- MYSQL_PASSWORD=****
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
networks:
- backend
Set the password that you want to use by replacing it into the ****
placeholders
Save the file (ctrl
+ o
) and exit (ctrl
+ x
)
Now create the container
docker-compose up -d
What we want to do now is to make the communication secure. It is going to manage our personal data, so we want the communication encrypted.
Navigate back to the Nginx Proxy Manager Web UI and set up a SSL certificate for your domain using web UI on the SSL Certificates
tab. This will only be possible once the domain has propagated.
From the Hosts
tab, set up a new proxy host for your domain and point it to the hostname nextcloud-app
on port 80. Note as the docker compose was set up using the external network the containers can resolve themselves using their names. On the SSL tab, select the certificate created earlier and then select the Force SSL
, HTTP/2 Support
and HSTS Enabled
options.
At this point we should be able to navigate to the domain / subdomain we created (remember the above https://myhome.mydomain.com
?) and login screen should appear. We should also see the secure connection set up. Now:
Create the admin user and untick the Install recommended apps, for performance reasons using the Raspberry Pi, install only what you need using the Nextcloud web gui later. After a short while, and possibly a couple of page refreshes, you should be able to log in and upload/download files from the nextcloud web gui.
Sometimes after the login the site does not redirect to the dashboard and presents the login screen again. Just login again.
Next steps are meant to polish the installation and to solve some warnings that appear. Mostly all warnings require that we do something internally to the instance, meaning to log in into the shell of the container. To do so we can use portainer or we can shell via the docker command. Other relate to set up specific configurations that we can do so by editing the configuration file or by executing the occ
tool. The following initial section is meant to setup the system so that configuring the system is easier later on. Bear with me.
This is one of the methods to enter into the container's shell.
http://tatooine:9000/
) and enter the credentials.Containers
in the left menunextcloud_nexcloud-app_1
container, under the Quick Actions columnA shell will open
This is another method to enter into the container's shell. Again, assuming that you're already SSHed into tatooine
:
docker exec -it nextcloud_nextcloud-app_1 /bin/bash
Dealing with configuration files means that we need to edit them, and to do so we better install nano
in our system. So once we are in the shell of our container, execute:
apt update && apt install nano
This will update the references of our packages and install the nano
editor.
occ
toolThere is a command line utility called occ
that you’ll need from time to time. occ
is inside the Nextcloud Docker container. To make life easier, we can add a bash alias in the Raspberry Pi's shell so that we can easily run occ
commands from outside the container.
Then, from the shell of the Raspberry (to be clear, outside of the container's shell):
Add a new alias in our home's .bashrc
file pointing to the tool inside the container:
echo alias occ=\'docker exec -it -u www-data nextcloud_nextcloud-app_1 php occ\' >> ~/.bashrc
Reload the .bashrc
file so the alias is loaded:
source ~/.bashrc
From now on, we can execute the occ
from outside the container comfortably. Try:
occ config:system:get overwritehost
Once logged in, click in the upper left user icon (your user icon!) and a dropdown menu appears. There click in Administration settings
. You should be directed to the Overview
section of the Administration
settings page. There there is a subsection Security & setup warnings
with some issues that we need to solve.
In the shell of the container, execute:
apt install libmagickcore-dev
In the shell of the container:
Edit the file /var/www/html/config/config.php
:
nano /var/www/html/config/config.php
At the end of the file, before the line that contains );
, add a line with the following key value pairs:
'default_phone_region' => 'DE',
Note that I placed the country code of Germany. You please add instead the one belonging to your country based on this page: ISO 3166-1 code.
Save the file (ctrl
+ o
) and exit (ctrl
+ x
)
caldav
and carddav
issuesThese appear only after installing the calendar apps, but just for the note to fix them:
Navigate to the Nginx Manager (remember: http://tatooine:81/
) and enter the credentials
Click in the Hosts
top menu
Click in the 3 vertical dots of the line of your Nextcloud proxy host (most likely will appear as myhome.mydomain.com
). A dropdown will pop up.
Select Edit
in the pop up menu. A modal window will appear
Select the Advanced
option from the top menu in the modal.
In the Custom Nginx configuration
add the following:
location /.well-known/carddav {
return 301 https://myhome.mydomain.com/remote.php/dav;
}
location /.well-known/caldav {
return 301 https://myhome.mydomain.com/remote.php/dav;
}
Click on Save
When accessing from the Android / iOS client apps, I suffered from a strange error that blocked me to log in, with a message telling Strict mode, no HTTP connection allowed!
. Digging deeper, from the Chrome Developer Tools Console I saw an error telling Refused to send form data from https://myhome.mydomain.com because it violates the following Content Security Policy directive: "form-action 'self'".
Turned out that it's a trusted proxies
issue and gets fixed executing the following occ
commands (remember that we're using our nice alias!) in the Raspberry shell:
occ config:system:set trusted_proxies 1 --value='127.0.0.1'
occ config:system:set overwritehost --value="myhome.mydomain.com"
occ config:system:set overwriteprotocol --value="https"
As this is a personal / home instance, I will reuse a spare Google account I have around as emailer. Google makes it a bit tricky to send emails as it now requires to activate the less secure app access
config for the account. Take a look at this Google Answer to learn how to do so.
Then, from the Nextcloud Admin Settings page, move to the Basic Settings page and set up the SMTP service as follows:
smtp.gmail.com
SSL/TLS
login
YES
465
That was a long read, but it's done faster than it seems. It took me a while to discover how to fix some of the issues, and that's why I include a closing References section. It's now around 2 months having my personal Nextcloud instance up and running with no issues, having it as a cloud service that auto-magically backs up the pics of my phone, syncs my Calendar and Bookmarks, and brings me a space to set my tasks and notes.
I am fascinated by the personal cloud service concept, and I would expect some more articles coming with some specifics like using an external storage, the proper set up for the photos cloud backup, some fine tuning for the pictures indexing, having LibreOffice available as an online doc tool too...