This file contains installation and customization instructions for Ilmomasiina, both for production and development.
If you want to change any of the following, you'll need to modify the code slightly and build your own Docker image (if using Docker):
- Hosting in a subfolder (instead of directly at
https://ilmo.your.domain/
) - Colors (
packages/ilmomasiina-components/src/styles/_definitions.scss
) - Header logo (TBD)
- Header title (build args or
packages/ilmomasiina-frontend/src/branding.ts
) - Footer links (as above)
- Favicon (
packages/ilmomasiina-frontend/public/*.png
) - Translations (
packages/ilmomasiina-*/src/locales/*.json
)
You can of course make further UI changes, but that is not documented.
How build arguments are passed depends on your build method:
- GitHub Actions: Workflow YAML file
- Docker Compose: Compose YAML file
- Local Docker build: build command
Note: If you fix bugs or add functionality, it would be very appreciated to create a pull request to the Tietokilta repository so we can potentially integrate them in our version. That also reduces your maintenance work when upgrading.
The easiest way to build and host your Docker image is using GitHub Actions. Your public repos
have free Actions time. The repository contains a workflow called
docker-build.yml
that can easily be customized with
variables to build and push an image for your organization.
Simply enable GitHub Actions
for your fork and modify the env
block in docker-build.yml
as instructed.
You'll also need to change the repository name in jobs.docker.if
to ensure the workflow runs -
it's automatically disabled on forks to avoid unnecessary errors.
With the current workflow setup, the following trigger an image build:
prod
branch pushes tagsprod
andlatest
staging
branch pushes tagstaging
- tags starting with
v
push semver tags (major.minor
and full version)
You can of course also build images locally.
docker build \
--build-arg BRANDING_HEADER_TITLE_TEXT='Ilmomasiina' \
--build-arg BRANDING_FOOTER_GDPR_TEXT='Tietosuoja' \
--build-arg BRANDING_FOOTER_GDPR_LINK='https://example.com' \
--build-arg BRANDING_FOOTER_HOME_TEXT='Kotisivu' \
--build-arg BRANDING_FOOTER_HOME_LINK='https://example.com' \
--build-arg BRANDING_LOGIN_PLACEHOLDER_EMAIL='[email protected]' \
-t ilmomasiina .
You can then use docker push
to a host of your choice, or run the container locally.
There are a few ways to run Ilmomasiina in production:
- Docker as Azure Web App (used by Tietokilta)
- Docker without Azure (same setup, should work)
- Docker Compose (currently untested)
- Without Docker (not recommended)
Other prerequisites:
- You'll need to bring your own email service.
- When running outside Azure and without Docker Compose, you'll need a separate database.
- When running outside Azure, you may also need to setup reverse proxying.
You'll need to generate at least two secrets for Ilmomasiina, NEW_EDIT_TOKEN_SECRET
and FEATHERS_AUTH_SECRET
.
These need to be different secure random strings with enough entropy. You can use a password generator and
generate passwords with at least 32 characters, or e.g. run openssl rand -hex 32
to generate them.
You'll need a MySQL/MariaDB or PostgreSQL database, and a user with full privileges to the DB. Instructions are provided here for PostgreSQL in Docker, and both MariaDB and PostgreSQL on Linux without Docker.
The app will automatically create the database schema upon startup.
Especially for development, running PostgreSQL with Docker may be the easiest option.
- Create the data directory:
mkdir data
- Start a container for PostgreSQL. You can change the values for user/password/DB name; you'll need to put
those in
.env
later.docker run -d \ --name ilmo_postgres \ -p 5432:5432 \ -e POSTGRES_USER=ilmo_user \ -e POSTGRES_PASSWORD=<add a password here> \ -e POSTGRES_DB=ilmomasiina \ -v ./data:/var/lib/postgresql/data \ postgres
- If you have the PostgreSQL client installed, try signing in:
psql -h localhost -U ilmo_user ilmomasiina
If you intend to run your own database, you can follow these instructions to install one on a Ubuntu or Debian system.
- Install MariaDB with
sudo apt install default-mysql-server
- MariaDB should start automatically. Run
sudo systemctl start mariadb
if necessary. - Open a MariaDB session with
sudo -u root mysql
. - Create the
ilmomasiina
database:CREATE DATABASE ilmomasiina;
- Create a new user for Ilmomasiina:
CREATE USER 'ilmo_user'@'localhost' IDENTIFIED BY '<add a password here>';
- Grant permissions on the new database:
GRANT ALL PRIVILEGES ON ilmomasiina.* TO 'ilmo_user'@'localhost';
- Exit the MariaDB session with
exit
. - Try signing in with your new user:
mysql -u ilmo_user -p
(don't put your password in the command).
- Install PostgreSQL with
sudo apt install postgresql
- PostgreSQL should start automatically. Run
sudo systemctl start postgresql
if necessary. - Open a PostgreSQL session with
sudo -u postgres psql
. - Create a new user for Ilmomasiina:
CREATE USER ilmo_user WITH PASSWORD '<add a password here>';
- Create the
ilmomasiina
database:CREATE DATABASE ilmomasiina WITH OWNER ilmo_user;
- Exit the PostgreSQL session with
exit
. - Try signing in with your new user:
psql -h localhost -U ilmo_user ilmomasiina
.
Ilmomasiina needs a way to send emails, both for signup confirmation and user passwords.
Mailgun and SMTP providers are currently supported. With minor changes, sending mail could be also done via Sendgrid or other services. Ilmomasiina uses Nodemailer - PRs welcome.
Note: If Ilmomasiina is run without an email provider configured, email contents will be printed to the console instead. This can be used for debugging.
Mailgun is relatively cheap and can be enabled via env variables.
MAILGUN_API_KEY
= Mailgun API key (created under Domain settings → Sending API keys)MAILGUN_DOMAIN
= Authorized sending domain in MailgunMAILGUN_HOST
=api.eu.mailgun.net
orapi.mailgun.net
depending on region
You can configure SMTP servers via env variables.
SMTP_HOST
= SMTP serverSMTP_PORT
= SMTP port, typically 25, 465 or 587SMTP_USER
= SMTP usernameSMTP_PASSWORD
= SMTP passwordSMTP_TLS
= typicallytrue
if using TLS (port 465),false
otherwise- Requiring STARTTLS is not currently supported - PRs welcome
Note: Using your own mail server gets you labelled as spam easily and should be avoided in production. User-facing email providers like Google might also not want you sending automatic email via them.
Tietokilta uses Azure to run Ilmomasiina. Azure gives credits for free to non-profits which should be enough for this.
Azure recently reduced free credits to $2000, which is barely enough to run a production-grade App Service (P1v2/P0v3). B-tier App Service Plans have been tried and at least B1 doesn't seem to handle load well.
- Optional: Build and push a customized Docker image, if necessary.
- Create an Azure Database for PostgreSQL Flexible Server (resource category Databases).
- Basics step: (screenshot)
- Server name: Choose freely.
- Region: Choose freely, but probably Europe.
- PostgreSQL version: 15
- Workload type: Development
- Compute + storage: Choosing Development should pick you a B-tier SKU. We're not entirely sure if these have enough performance in practice.
- Authentication method: PostgreSQL authentication only
- Admin username: Choose freely.
- Admin password: Choose freely & save for later.
- Networking step:
- Connectivity method: Public
- Check Allow public access from any Azure service within Azure to this server
- Security and Tags can be skipped
- Basics step: (screenshot)
- From the Databases page, create a database on that server.
- The name can be chosen freely.
- Recommended: Create a user on the server and grant access to the database.
- You can technically also use the PostgreSQL admin user if you don't use the database for anything else.
- This requires connecting to the database manually:
- From the Networking page, under Firewall rules, add a rule for current client IP address and save. Wait a bit for the changes to apply.
- From the Connect tab, copy the
psql
command to your shell:psql -h {postgres-server-name}.postgres.database.azure.com -p 5432 -U {admin_user_name} {db_name}
- This all-in-one command is under Connect from browser or locally. You can also use the variant with environment variables.
- The portal was a bit buggy for me and I needed to add the database name manually.
- Create a new user for Ilmomasiina:
CREATE USER ilmo_user WITH PASSWORD '<add a password here>';
- Grant access to the database for the new user:
GRANT ALL PRIVILEGES ON SCHEMA public TO ilmo_user;
- Exit the PostgreSQL session with
exit
. - Try signing in with your new user: replace your admin username in the
psql
command with the new user (above:ilmo_user
).
- Create an Azure Web App (resource category Web).
- Basics step: (screenshot)
- Web App name: Choose freely, will appear in your URLs as
https://{your-app-name}.azurewebsites.net/
. - Publish: Docker Container
- Operating System: Linux
- Region: Choose freely, but probably same as your database.
- Linux Plan: Reuse an existing one or create a new one.
- Pricing plan: B2 has been tested and isn't very performant. You may want to go for P1v2/P0v3 if your budget allows.
- Web App name: Choose freely, will appear in your URLs as
- Database step can be skipped
- Docker step: (screenshot)
- Options: Single Container
- Image Source: Private Registry
- Server URL:
https://ghcr.io
- Image and tag:
- Non-customized Tietokilta image, latest stable version:
tietokilta/ilmomasiina:latest
- Non-customized Tietokilta image, pinned version:
tietokilta/ilmomasiina:2.0.0
(example) - Customized image, built in CI or uploaded by you:
yourorg/ilmomasiina:latest
(example)
- Non-customized Tietokilta image, latest stable version:
- If you use Docker Hub or Azure Container Registry, change these accordingly
- Networking step:
- Enable public access: On
- Monitoring and Tags can be skipped
- Basics step: (screenshot)
- Read .env.example. Set relevant variables as Application settings on the Configuration page. You'll need at least:
PORT
andWEBSITES_PORT
must match (you can set both to 3000)DB_DIALECT
=postgres
DB_HOST
= Domain name of your PostgreSQL server (from Connect page)DB_USER
= username of PostgreSQL user (above:ilmo_user
)DB_PASSWORD
= password of PostgreSQL userDB_DATABASE
= name of PostgreSQL databaseDB_SSL
=true
(required with Azure's default config)NEW_EDIT_TOKEN_SECRET
= secure random string (see Generating secrets)FEATHERS_AUTH_SECRET
= secure random string (see Generating secrets)MAIL_FROM
= "From" email for system messagesMAILGUN_*
orSMTP_*
for email credentials (see Email sending)BASE_URL
=https://{your-app-name}.azurewebsites.net/
BRANDING_MAIL_FOOTER_TEXT
andBRANDING_MAIL_FOOTER_LINK
(may be empty)
- Access the app at
https://{your-app-name}.azurewebsites.net/
.- If something is broken, check the Log stream page or read logs via
https://{your-app-name}.scm.azurewebsites.net/
.
- If something is broken, check the Log stream page or read logs via
You can use Docker Compose to run both a database and production container locally. Currently, we don't actively test this configuration.
- Create a
.env
file at the root of this repository. You can copy .env.example to begin and read the instructions within. - Optional: Modify
args
indocker-compose.prod.yml
for frontend customization. - Optional: Make customizations in other files if necessary.
- Run
docker-compose -f docker-compose.prod.yml up
manually or e.g. viasystemd
. - Access the app at http://localhost:8000.
If you don't want to use Docker Compose, or already have a database, you can run a plain Docker container locally.
- Create a
.env
file at the root of this repository. You can copy .env.example to begin and read the instructions within. - Optional: Make customizations in other files if necessary.
- After this, build your customized image via GitHub Actions or locally.
- Run the container manually or with e.g.
systemd
.docker run -it --rm --init --env-file=.env -p 3000:3000 ghcr.io/tietokilta/ilmomasiina:latest
- You might have to add stuff here to e.g. allow database connections.
- In particular,
--network host
allows connecting to a database running onlocalhost
on the host machine. Remove-p 3000:3000
when using this.
- In particular,
- This runs a non-customized Tietokilta image from the latest stable version. For other options, replace
ghcr.io/tietokilta/ilmomasiina:latest
with:- Non-customized Tietokilta image, pinned version:
ghcr.io/tietokilta/ilmomasiina:2.0.0
(example) - Customized image, built in CI or uploaded by you:
ghcr.io/yourorg/ilmomasiina:latest
(example) - Locally built image:
ilmomasiina
(what was after-t
indocker build
)
- Non-customized Tietokilta image, pinned version:
- You might have to add stuff here to e.g. allow database connections.
- Access the app at http://localhost:3000.
You can also set up a production deployment without Docker. This method is not recommended.
- Install a suitable Node version (e.g. using nvm).
- Run
npm install -g pnpm@8
to install pnpm. Then runpnpm install --frozen-lockfile
to setup cross-dependencies between packages and install other dependencies. - Create a
.env
file at the root of this repository. You can copy .env.example to begin and read the instructions within. - Optional: Make customizations in other files if necessary.
- Run
npm run clean
followed bynpm run build
. - Use e.g.
systemd
orpm2
(npm install -g pm2
) to run the server process:node packages/ilmomasiina-backend/dist/bin/server.js
- Access the app at http://localhost:3000.
If you want to serve ilmomasiina from a subdirectory of your website, you need to set up reverse proxying.
This will also require changing the PATH_PREFIX
env variable when building the frontend or container.
The examples assume /ilmo/
is the subdirectory and PORT
is 3000 - adjust accordingly if needed.
The examples use the backend server to serve the frontend files, which is less efficient than using a proper web server to serve them. (PRs welcome with instructions on how to set up a better method.)
This approach requires access to Apache config.
# proxy https://your.website/ilmo/whatever to http://127.0.0.1:3000/whatever
<Location "/ilmo/">
ProxyPass "http://127.0.0.1:3000/"
</Location>
This approach works both in .htaccess
(with suitable AllowOverride
s) or Apache config.
In Apache config, you may need to change the rules slightly.
It can use either the backend server or Apache to also serve the frontend files. If Apache is to be used, the built frontend must be placed in the folder. (untested)
RewriteEngine On
# redirect https://your.website/ilmo to https://your.website/ilmo/
RewriteBase /
RewriteRule ^ilmo$ ilmo/ [NC,R=301,L]
# always proxy https://your.website/ilmo/ to http://127.0.0.1:3000/
RewriteRule ^ilmo/(.*)$ http://127.0.0.1:3000/$1 [P,L]
# proxy https://your.website/ilmo/whatever to http://127.0.0.1:3000/whatever,
# but only if the file doesn't exist in the webroot
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ilmo/(.*)$ http://127.0.0.1:3000/$1 [P,L]
In development, we recommend running without Docker. It's easier to use in most cases, but you'll need to set up your own database. That is easiest to do with Docker.
There's also a Docker Compose setup with some significant drawbacks.
Currently Prettier is not used in the project, so here is a recommended .vscode/settings.json
config:
{
"[typescript]": {
"editor.defaultFormatter": "vscode.typescript-language-features"
},
"[typescriptreact]": {
"editor.defaultFormatter": "vscode.typescript-language-features"
}
}
- Install a suitable Node version (e.g. using nvm).
- Install a database.
- See Database setup for instructions on setting up MySQL.
- You can also use Docker for a database.
- SQLite may also work, but is currently untested.
- Create a
.env
file at the root of this repository. You can copy .env.example to begin and read the instructions within. - Run
npm install -g pnpm@8
to install pnpm. Then runpnpm install --frozen-lockfile
to setup cross-dependencies between packages and install other dependencies. - Run
npm start
orpnpm start
. This will start the frontend and backend dev servers in parallel.- If you want cleaner output, you can run
npm start
separately inpackages/ilmomasiina-frontend
andpackages/ilmomasiina-backend
. - Alternatively, you can use
pnpm run --filter=@tietokilta/ilmomasiina-frontend start
(and similar for the backend).
- If you want cleaner output, you can run
- Access the app at http://localhost:3000.
The entire development setup can also be run within Docker using Docker Compose. The docker-compose dev setup is located at the root of this repository, and contains a pre-configured PostgreSQL server, so an external database server is not required.
- Create a
.env
file at the root of this repository. You can copy .env.example to begin and read the instructions within. - Go to the repository root and run
docker-compose up
. This builds the dev container and starts the frontend and backend servers in parallel. - Access the app at http://localhost:3000.
Due to how the dev Docker is set up, you will still need to rebuild the development image if you change the dependencies, package.json or ESLint configs. You'll also need Node.js and pnpm installed locally to do that.