Skip to content

Install Cozy on Ubuntu 20.04 LTS focal fossa

Introduction

Cozycloud provides Debian packages and installation instructions for Debian 10 buster from installation packages. However, there is no published packages for Ubuntu.

This documentation describes how to install Cozy from sources on an Ubuntu 20.04 LTS focal fossa server. We will also see how to host multiple Cozy instances on the same server, how to activate online edition for office documents and how to upgrade cozy-stack.

Requirements

The installation procedure requires:

  • An Ubuntu 20.04 LTS focal fossa server
  • A domain name (mandatory to host Cozy instances secured with https and accessible from internet). In this docuemnt, we will use domain.example as an example. You will replace it with your own domain name throughout the explanation. The address of your Cozy instance will be cozy.domain.example
  • Good system administration knowledge. Despite documentation’s goal is to be pretty straightforward to follow, there are some tricky and technical parts.

During installation, you will also define:

  • a CouchDB administration password
  • a CouchDB database access password
  • a cozy-stack admin password
  • You will need to provide your email address for Let’s Encrypt SSL certificate validation and your Cozy instance creation

Couchdb

Configure CouchDB package repository:

sudo apt update && sudo apt install -y curl apt-transport-https gnupg
curl https://couchdb.apache.org/repo/keys.asc | gpg --dearmor | sudo tee /usr/share/keyrings/couchdb-archive-keyring.gpg >/dev/null 2>&1
echo "deb [signed-by=/usr/share/keyrings/couchdb-archive-keyring.gpg] https://apache.jfrog.io/artifactory/couchdb-deb/ $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/couchdb.list >/dev/null

Install Couchdb:

sudo apt update
sudo apt install -y couchdb

Duing CouchDB installation, choose Standalone mode and define admin password.

Validate CouchDB is working:

curl http://localhost:5984/
{"couchdb":"Welcome","version":"3.2.1","git_sha":"244d428af","uuid":"f7b83554fa2eb43778963d18a1f92211","features":["access-ready","partitioned","pluggable-storage-engines","reshard","scheduler"],"vendor":{"name":"The Apache Software Foundation"}}

Finally, create a database user and password for cozy-stack:

read -p "Couchdb password for cozy user: " -r -s COUCH_PASS
curl -fsX PUT -u "admin:adminpwd" "http://localhost:5984/_node/couchdb@127.0.0.1/_config/admins/cozy" --data "\"${COUCH_PASS}\""

In this command line, adminpwd should be replaced by CouchDB admin password you defined during CouchDB installation.

NodeJS

To be able to run Cozy connectors and gather all your data, cozy-stack needs NodeJS version 12 or 16. This documents gives instructions to instal NodeJS 16.

Configure NodeJS 16 package repository:

KEYRING=/usr/share/keyrings/nodesource.gpg
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | gpg --dearmor | sudo tee "$KEYRING" >/dev/null
echo "deb [signed-by=$KEYRING] https://deb.nodesource.com/node_16.x $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/nodesource.list >/dev/null
echo "deb-src [signed-by=$KEYRING] https://deb.nodesource.com/node_16.x $(lsb_release -sc) main" | sudo tee -a /etc/apt/sources.list.d/nodesource.list >/dev/null

Install NodeJS:

sudo apt update
sudo apt install -y nodejs
sudo ln -s /usr/bin/node /usr/bin/nodejs

Go

cozy-stack is developped in Go language so we need to install the Go compiler to be able to compile cozy-stack sources:

wget -O /tmp/go1.17.3.linux-amd64.tar.gz https://go.dev/dl/go1.17.3.linux-amd64.tar.gz
sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzvf /tmp/go1.17.3.linux-amd64.tar.gz
echo "export PATH=\"\$PATH:/usr/local/go/bin\"" | sudo tee /etc/profile.d/golang.sh > /dev/null
source /etc/profile.d/golang.sh

Test Go installation is fine with:

go version
go version go1.17.3 linux/amd64

Cozy-stack

First, install requirements:

sudo apt install -y imagemagick libprotobuf-c1 fonts-lato

Get the source code:

sudo apt install -y git
sudo git clone https://github.com/cozy/cozy-stack.git /opt/cozy-stack

Then compile the program:

cd /opt/cozy-stack
scripts/build.sh release $(go env GOPATH)/bin/cozy-stack

The compilation generate a binary file under $GOPATH/bin/cozy-stack

You can test it with:

$(go env GOPATH)/bin/cozy-stack version
1.5.0-5-gcbdf012d

You then have to create a user to run cozy-stack:

sudo addgroup --quiet --system cozy
sudo adduser --quiet --system --home /var/lib/cozy \
             --no-create-home --shell /usr/sbin/nologin \
             --ingroup cozy cozy-stack

And install it:

sudo install -o root -g root -m 0755 -T \
             $(go env GOPATH)/bin/cozy-stack /usr/bin/cozy-stack
sudo sh -c 'cozy-stack completion bash > /etc/bash_completion.d/cozy-stack'
source /etc/bash_completion.d/cozy-stack
sudo install -o root -g root -m 0755 -d /etc/cozy
sudo install -o root -g cozy -m 0750 -d /var/log/cozy
sudo install -o cozy-stack -g cozy -m 750 -d /usr/share/cozy
sudo install -o cozy-stack -g cozy -m 750 \
             /opt/cozy-stack/scripts/konnector-node16-run.sh \
             /usr/share/cozy/konnector-node16-run.sh
sudo install -o cozy-stack -g cozy -m 750 -d /var/lib/cozy

And create configuration:

read -p "Cozy stack admin password: " -r -s COZY_PASS
cat <<EOF | sudo tee /etc/cozy/cozy.yml >/dev/null
host: 127.0.0.1
port: 8080

admin:
  host: 127.0.0.1
  port: 6060

couchdb:
  url: http://cozy:${COUCH_PASS}@127.0.0.1:5984/

fs:
  url: file:///var/lib/cozy

vault:
  credentials_encryptor_key: /etc/cozy/vault.enc
  credentials_decryptor_key: /etc/cozy/vault.dec

konnectors:
  cmd: /usr/share/cozy/konnector-node16-run.sh

log:
  level: info
  syslog: true

registries:
  default:
  - https://apps-registry.cozycloud.cc/selfhosted
  - https://apps-registry.cozycloud.cc/banks
  - https://apps-registry.cozycloud.cc/
EOF
sudo chown cozy-stack:cozy /etc/cozy/cozy.yml
sudo chmod 0644 /etc/cozy/cozy.yml
sudo sh -c "COZY_ADMIN_PASSPHRASE=\"${COZY_PASS}\" cozy-stack config passwd /etc/cozy/cozy-admin-passphrase"
sudo chown cozy-stack:cozy /etc/cozy/cozy-admin-passphrase
sudo cozy-stack config gen-keys /etc/cozy/vault
sudo chown cozy-stack:cozy /etc/cozy/vault.enc /etc/cozy/vault.dec
sudo chmod 0600 /etc/cozy/vault.enc /etc/cozy/vault.dec

Finally, configure systemd to automatically launch cozy-stack on boot:

cat <<EOF | sudo tee /usr/lib/systemd/system/cozy-stack.service >/dev/null
[Unit]
Description=Cozy service
Wants=couchdb.service
After=network.target couchdb.service

[Service]
User=cozy-stack
Group=cozy
WorkingDirectory=/var/lib/cozy/
PermissionsStartOnly=true
ExecStart=/usr/bin/cozy-stack serve
Restart=always

[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable cozy-stack
sudo systemctl start cozy-stack

You can validate everything went well and cozy-stack is running thiw way:

curl http://localhost:8080/version
{"build_mode":"production","build_time":"2021-12-01T13:12:36Z","runtime_version":"go1.17.3","version":"1.5.0-5-gcbdf012d"}

Nginx

First create a DNS entry in your domain for cozy.domain.example and *.cozy.domain.example pointing at your server. For example:

cozy     1h     IN         A     <your_server_IP>
*.cozy   1h     IN     CNAME     cozy

Then install Nginx:

sudo apt install -y nginx certbot

Generate SSL certificate with certbot:

DOMAIN=domain.example
EMAIL="<your email address>"
sudo certbot certonly --email "${EMAIL}" --non-interactive --agree-tos --webroot -w /var/www/html -d cozy.${DOMAIN} $(printf -- " -d %s.cozy.${DOMAIN}" home banks contacts drive notes passwords photos settings store)

Create nginx reload script for your certificate to be reloaded each time it is automatically refreshed, every 3 months:

cat <<EOF | sudo tee /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
#!/bin/bash
nginx -t -q && nginx -s reload
EOF
chmod 0755 /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh

Configure nginx:

DOMAIN=domain.example
cat <<EOF | sudo tee /etc/nginx/sites-available/cozy.${DOMAIN} > /dev/null
server {
    listen 80;
    listen [::]:80;

    root /var/www/html;
    server_name *.cozy.${DOMAIN} cozy.${DOMAIN};

    location /.well-known {
        alias /var/www/html/.well-known;
    }

    location / {
        return         301 https://\$host\$request_uri;
    }
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    ssl_certificate /etc/letsencrypt/live/cozy.${DOMAIN}/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/cozy.${DOMAIN}/privkey.pem;

    server_name *.cozy.${DOMAIN} cozy.${DOMAIN};
    access_log /var/log/nginx/cozy.${DOMAIN}.access.log;
    error_log /var/log/nginx/cozy.${DOMAIN}.error.log;

    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains;";
    client_max_body_size 1g;

    location / {
        proxy_pass http://localhost:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade \$http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host \$host;
        proxy_set_header X-Forwarded-For \$remote_addr;
    }
}
EOF
sudo ln -s ../sites-available/cozy.${DOMAIN} /etc/nginx/sites-enabled/
sudo systemctl reload nginx

You can then test from your browser by visiting https://cozy.domain.example and you should see a page telling you this Cozy instance doesn’t exist yet. This is the sign that everything went well and the only part left is to create the instance.

Cozy instance creation

Create your Cozy instance:

DOMAIN=domain.example
EMAIL=<your email address>
[[ -z "${COZY_PASS}" ]] && read -p "Cozy stack admin password: " -r -s COZY_PASS
COZY_ADMIN_PASSWORD="${COZY_PASS}" cozy-stack instances add --apps home,banks,contacts,drive,notes,passwords,photos,settings,store --email "${EMAIL}" --locale fr --tz "Europe/Paris" cozy.${DOMAIN}

You can of course adapt your language (locale) and choose english (en) or spanish (es) and choose another timezone (tz).

Note the “Registration token” this command returns and visit from your browser https://cozy.domain.example?registerToken=<registration_token> substituting domain.example with your real domain name and <registration_token> with the “Registration token” you got. You will be prompted to define your Cozy password and you will be able to start using your self-hosted Cozy.

Et voilà !

Your Cozy is not fully operational! Its address is https://cozy.domain.example (remplace domain.example by your own domain name) You can then start installing connectors from store to automatically gather your data, save your passwords in cozy-pass, store your files in cozy-drive and install cozy-desktop client on your PC to synchronize your Cozy content with a local folder.

Below are some bonuses 😉

Hosting more than one Cozy instance on the same server

Having its own selfhosted Cozy instance is nice but hosting Cozy instances for friends and family is a must! Here is how to add more Cozy instances on the same server.

The first Cozy instance we added was https://cozy.domain.example. We will create a second Cozy instance for Mary with address https://mary.domain.example (Replace domain.example with your own domain name and mary with what you want to uniquely identify the Cozy instance.

So we will need:

  • Our domain name. We still use domain.example in this documentation
  • The new Cozy instance’s “slug”, which is its unique identifier. We will use mary here for example. The address for this new Cozy instance will the be in the form https://<slug>.<domain>, for example here https://mary.domain.example

First, let’s put all that important information in variables:

DOMAIN=domain.example
EMAIL=<your email addresse>
NEWSLUG=mary
NEWEMAIL=<Mary's email address>

Create DNS entries for this Cozy instance. For example:

mary     1h     IN         A     <your_server_IP>
*.mary   1h     IN     CNAME     mary

Create Nginx base configuration for this Cozy instance:

cat <<EOF | sudo tee /etc/nginx/sites-available/${NEWSLUG}.${DOMAIN} > /dev/null
server {
    listen 80;
    listen [::]:80;

    root /var/www/html;
    server_name *.${NEWSLUG}.${DOMAIN} ${NEWSLUG}.${DOMAIN};

    location /.well-known {
        alias /var/www/html/.well-known;
    }

    location / {
        return         301 https://\$host\$request_uri;
    }
}
EOF
sudo ln -s ../sites-available/${NEWSLUG}.${DOMAIN} /etc/nginx/sites-enabled/
sudo systemctl reload nginx

Generate SSL certificate using certbot:

sudo certbot certonly --email "${EMAIL}" --non-interactive --agree-tos --webroot -w /var/www/html -d ${NEWSLUG}.${DOMAIN} $(printf -- " -d %s.${NEWSLUG}.${DOMAIN}" home banks contacts drive notes passwords photos settings store)

Finalize Nginx configuration:

cat <<EOF | sudo tee -a /etc/nginx/sites-available/${NEWSLUG}.${DOMAIN} > /dev/null

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    ssl_certificate /etc/letsencrypt/live/${NEWSLUG}.${DOMAIN}/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/${NEWSLUG}.${DOMAIN}/privkey.pem;

    server_name *.${NEWSLUG}.${DOMAIN} ${NEWSLUG}.${DOMAIN};
    access_log /var/log/nginx/${NEWSLUG}.${DOMAIN}.access.log;
    error_log /var/log/nginx/${NEWSLUG}.${DOMAIN}.error.log;

    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains;";
    client_max_body_size 1g;

    location / {
        proxy_pass http://localhost:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade \$http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host \$host;
        proxy_set_header X-Forwarded-For \$remote_addr;
    }
}
EOF
sudo systemctl reload nginx

Create Cozy instance:

[[ -z "${COZY_PASS}" ]] && read -p "Cozy stack admin password: " -r -s COZY_PASS
COZY_ADMIN_PASSWORD="${COZY_PASS}" cozy-stack instances add --apps home,banks,contacts,drive,notes,passwords,photos,settings,store --email "${NEWEMAIL}" --locale fr --tz "Europe/Paris" ${NEWSLUG}.${DOMAIN}

Note the “Registration token” the last command gives you and send Mary the following url: https://mary.domain.example?registerToken=<registration_token>, substituting domain.example with your own domain name, mary with the slug you chose for this new instance and <registration_token> with the “Registration token” returned by the last command. By visiting this address with her browser, Mary will be able to define its password and start using her Cozy.

Online edition of office documents

Online office document edition functionality based on OnlyOffice is optional. You can use your Cozy without activating it. It let you edit your office documents online directly in your browser, however it requires more resources on your server.

To activate this functionality, you need to install OnlyOffice document server and configure cozy-stack to access it. OnlyOffice document server can be installed on the same server or on another server at your convenience. This documentation explain how to install it on the same server.

Onlyoffice

Onlyoffice requires PostgreSQL and RabbitMQ so we will start by installing them.

Install PostgreSQL and create database

sudo apt update
sudo -i -u postgres psql -c "CREATE DATABASE onlyoffice;"
sudo -i -u postgres psql -c "CREATE USER onlyoffice WITH password 'onlyoffice';"
sudo -i -u postgres psql -c "GRANT ALL privileges ON DATABASE onlyoffice TO onlyoffice;

The second command create a database user names onlyoffice with password onlyoffice. We advise you to choose a more secure password in real life.

Install RabbitMQ

sudo apt install -y rabbitmq-server

Install Onlyoffice Documentserver

Configure package repository

sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys CB2DE8E5
echo "deb https://download.onlyoffice.com/repo/debian squeeze main" | sudo tee /etc/apt/sources.list.d/onlyoffice.list
sudo apt update

Install microsoft fonts

sudo apt install -y ttf-mscorefonts-installer

When asked, accept EULA

Install OnlyOffice Documentserver

sudo apt install -y onlyoffice-documentserver

When asked, enter database password we created when installing postgreSQL and created database.

Then restart Nginx

sudo systemctl reload nginx

Configure HTTPS for OnlyOffice

Create a DNS entry for OnlyOffice targeting your server. For example:

onlyoffice     1h     IN         A     <your_server_IP>

Generate SSL certificate:

EMAIL=<your email address>
DOMAIN=domain.example
sudo bash /usr/bin/documentserver-letsencrypt.sh "${EMAIL}" "onlyoffice.${DOMAIN}"

Configure onlyoffice:

sudo cp -f /etc/onlyoffice/documentserver/nginx/ds-ssl.conf.tmpl /etc/onlyoffice/documentserver/nginx/ds.conf

Edit file /etc/onlyoffice/documentserver/nginx/ds.conf and

  • replace {{SSL_CERTIFICATE_PATH}} with /etc/letsencrypt/live/onlyoffice.domain.example/fullchain.pem
  • replace {{SSL_KEY_PATH}} with /etc/letsencrypt/live/onlyoffice.domain.example/privkey.pem

Be careful each line end with semicolons (;).

Restart OnlyOffice and Nginx:

sudo supervisorctl restart all
sudo systemctl restart nginx

You can now test onlyoffice is accessible from your browser at https://onlyoffice.domain.example.

Configure cozy-stack for OnlyOffice

Update configuration file:

DOMAIN=domain.example
cat <<EOF | sudo tee -a /etc/cozy/cozy.yml > /dev/null
office:
  default:
    onlyoffice_url: https://onlyoffice.${DOMAIN}/
EOF

Restart cozy-stack:

sudo systemctl restart cozy-stack

Activate functionality:

cozy-stack features defaults '{"drive.office": {"enabled": true, "write": true}}'

You can now upload an office document in cozy-drive and start editing it online by clicking on it or start a new empty document for the “New document” menu.

The drive.office feature flag has other options for customising the experience with OnlyOffice: - enabled: Enables OnlyOffice (OO) - write: Gives the right to edit. Otherwise OO opens in read mode and a modal is displayed on editing actions to warn that the functionality is blocked - defaultMode: By default, OO opens in read mode (view). It can be switched to edit with the edit parameter. - touchScreen: Corresponds to Cozy mobile applications or a browser with a screen width of 1023px or less or a user-agent on an iOS or Android operating system * enabled: Enable OnlyOffice (OO) * readOnly: Disables edit mode. You can no longer create new documents, only open existing ones in read mode without an edit button - mobile: Corresponds to the browser with a screen width of 768px or less * defaultMode: By default, the opening mode is the same as the main defaultMode. It can be changed to either view reading or edit editing

Example :

{
    "enabled": true,
    "write": true,
    "defaultMode": "view"
    "touchScreen": {
        "enabled": true
        "readOnly": false
    },
    "mobile": {
        "defaultMode": "view"
    }
}

Update cozy-stack

Applications inside your Cozy are automatically updated, however, cozy-stack application running on your server must be updated from time to time (once every 3 month is a good compromise between too much and too few). Here is how to upgrade cozy-stack:

Update source code:

cd /opt/cozy-stack
sudo git pull

compile source code:

cd /opt/cozy-stack
scripts/build.sh release $(go env GOPATH)/bin/cozy-stack

You can test compilation produced a valid binary with:

$(go env GOPATH)/bin/cozy-stack version
1.5.0-9-g1eac6802

Install new generated binary:

sudo install -o root -g root -m 0755 -T \
             $(go env GOPATH)/bin/cozy-stack /usr/bin/cozy-stack

Restart cozy-stack:

sudo systemctl restart cozy-stack

Et voilà, you just upgraded cozy-stack to the latest version. pretty easy.

References