Merge pull request #12 from inventaire/package-prod

This commit is contained in:
maxlath
2025-02-28 11:43:18 +01:00
14 changed files with 566 additions and 185 deletions

7
.gitignore vendored
View File

@@ -1,5 +1,6 @@
inventaire
.docker
.env
.eslintcache
certbot
data
log
configs/docker.ini

227
README.md
View File

@@ -1,202 +1,109 @@
Run [Inventaire](https://github.com/inventaire/inventaire) in Docker
# Inventaire Suite
This repository is meant to support running Inventaire for testing and development. For production, see [inventaire-deploy](https://github.com/inventaire/inventaire-deploy).
The Inventaire Suite is a containerized, production-ready Inventaire system that allows you to self-host a knowledge graph similar to [inventaire.io](https://inventaire.io).
It is composed of several services:
* **[Inventaire](https://hub.docker.com/r/inventaire/inventaire)**: a Docker image packaging:
* the Inventaire [server](https://git.inventaire.io/inventaire/), which comes with its embedded database: LevelDB
* the Inventaire [client](https://git.inventaire.io/inventaire-client/)
* **[CouchDB](https://hub.docker.com/_/couchdb)**: the primary database used by the Inventaire server
* **[Elasticsearch](https://hub.docker.com/_/elasticsearch)**: a secondary database used by Inventaire for text and geographic search features
* **[Nginx](https://hub.docker.com/_/nginx)**: a reverse proxy with TLS termination thank to Let's Encrypt [certbot](https://hub.docker.com/r/certbot/certbot).
The service orchestration is implemented using Docker Compose.
> 🔧 This document is for people wanting to self-host the full Inventaire Suite. If you are looking for the individual Inventaire image, head over to [hub.docker.com/r/inventaire/inventaire](https://hub.docker.com/r/inventaire/inventaire).
> 💡 This document presumes familiarity with basic Linux administration tasks and with Docker and Docker Compose.
## Summary
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
- [Requirements](#requirements)
- [Install](#install)
- [Quickstart](#quickstart)
- [Requirements](#requirements)
- [Hardware](#hardware)
- [Software](#software)
- [Domain name](#domain-name)
- [Open ports](#open-ports)
- [Initial setup](#initial-setup)
- [Download this repository](#download-this-repository)
- [Initial configuration](#initial-configuration)
- [Generate a TLS certificate](#generate-a-tls-certificate)
- [Usage](#usage)
- [Tips](#tips)
- [Fixtures](#fixtures)
- [Tests](#tests)
- [Push git commits](#push-git-commits)
- [Rootless Docker](#rootless-docker)
- [Run inventaire server and client outside of Docker](#run-inventaire-server-and-client-outside-of-docker)
- [Troubleshooting](#troubleshooting)
- [Elasticsearch errors](#elasticsearch-errors)
- [Quieting CouchDB notice](#quieting-couchdb-notice)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
## Requirements
## Quickstart
### Requirements
#### Hardware
* Network connection with a public IP address
* 4 GB RAM
* 10 GB free disk space
- [docker-compose](https://docs.docker.com/compose/gettingstarted/) up and ready
- git
#### Software
* [Docker](https://docs.docker.com/get-started/get-docker/) >= v22.0
* [Docker compose](https://docs.docker.com/compose/gettingstarted/) >= v2
* [git](https://git-scm.com/)
## Install
#### Domain name
> Ignore this section if you are just testing on your local machine
You need a DNS records that resolves to your machine's public IP address
#### Open ports
> Ignore this section if you are just testing on your local machine
Your machine's firewall should let the http ports (`80` and `443`) open.
## Initial setup
### Download this repository
```sh
git clone https://github.com/inventaire/docker-inventaire.git
git clone https://git.inventaire.io/docker-inventaire.git
cd docker-inventaire
```
Clone `inventaire` core application [server](https://github.com/inventaire/inventaire)
### Initial configuration
Copy the `dotenv` file to `.env`
```sh
cp dotenv .env
```
and open this new `.env` file with a text editor to customize the variables (mainly adding your own domain name, and setup a couchdb password)
#### Generate a TLS certificate
> Ignore this section if you are just testing on your local machine
Generate the first TLS certificate with Let's Encrypt
```sh
git clone https://github.com/inventaire/inventaire.git
docker run -it --rm --name certbot -p 80:80 -v "$(pwd)/certbot/conf:/etc/letsencrypt" certbot/certbot certonly --standalone
```
Build
```sh
docker-compose build
```
Download Node dependencies and install the [client repository](https://github.com/inventaire/inventaire-client):
```sh
docker-compose run --rm inventaire npm install
```
Configure inventaire so that it can connect to CouchDB. For that, create a file `config/local.cjs` with the following command:
```sh
echo "module.exports = {
db: {
username: 'yourcouchdbusername',
password: 'yourcouchdbpassword'
}
}
" > ./inventaire/config/local.cjs
```
NB: Those username and password should match the `COUCHDB_USER` and `COUCHDB_PASSWORD` environment variables set in `docker-compose.yml`
## Usage
Start CouchDB, Elasticsearch, and the Inventaire [server](https://github.com/inventaire/inventaire) in development mode (modifications to the server files will reload the server), by default on port 3006
Start all the services (Nginx, CouchDB, Elasticsearch, and the Inventaire [server](https://git.inventaire.io/inventaire)) in production mode:
```sh
docker-compose up
docker compose up -d
```
To also work on the [client](https://github.com/inventaire/inventaire-client), you need to also start the webpack dev server:
Alternatively, to test locally, you can start only Inventaire and its dependencies (CouchDB and Elasticsearch) without Nginx, with the following command:
```sh
cd inventaire/client
npm run watch
docker compose up inventaire
```
## Tips
General tips on how to run Inventaire can be found in the [server repository docs](https://github.com/inventaire/inventaire/tree/main/docs). Here after are some additional Docker-specific tips.
### Fixtures
In case you would like to play with out-of-the-box data.
Run api tests to populate tests dbs (see Tests section)
```sh
docker-compose -f docker-compose.yml -f docker-compose.test.yml exec inventaire npm run test-api
```
- Replicate `*-tests` dbs documents into `*` dbs
```sh
`docker-compose exec inventaire npm run replicate-tests-db`
```
### Tests
Start services with test environnement with [multiple compose files](https://docs.docker.com/compose/extends/#understanding-multiple-compose-files)
```sh
docker-compose -f docker-compose.yml -f docker-compose.test.yml up
```
Execute tests script
```sh
docker-compose exec inventaire npm run test-api
```
or execute directly the test command
```sh
docker-compose exec inventaire npm test /opt/inventaire/path/to/test/file
```
Tip : create a symbolic link on your machine between the inventaire folder and docker working directory on your machine at `/opt/`, in order to autocomplete path to test file to execute
```sh
sudo ln ~/path/to/inventaire-docker/inventaire /opt -s
```
Alternatively, as root in inventaire container:
```sh
mkdir /supervisor/path/to/inventaire
ln -s /opt/ /supervisor/path/to/inventaire
```
### Push git commits
To keep things simple, this installation steps above clone repositories in https, but if you want to push to a branch with ssh, you will probably need to change the repositories `origin`:
```sh
cd inventaire
git remote set-url origin git@github.com:inventaire/inventaire.git
cd client
git remote set-url origin git@github.com:inventaire/inventaire-client.git
```
### Rootless Docker
Docker Engine v20.10 is now available in rootless mode. If you would like to try it, you may follow the [official guide](https://docs.docker.com/engine/security/rootless/) (including command `export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock`).
Start the inventaire install steps above, before installing dependencies, make sure that the owner of inventaire folder is the same as the owner inside the container.
Delete `network_host` occurences from `docker-compose.yml` and adapt the `config/local.cjs` in consequence:
```js
module.exports = {
protocol: 'http',
port: 3006,
host: 'inventaire',
db: {
username: 'couchdb',
password: 'password',
protocol: 'http',
hostname: 'couch'
},
elasticsearch: {
host:'http://elasticsearch:9200'
}
}
```
### Run inventaire server and client outside of Docker
It can sometimes be more convenient to keep CouchDB and Elasticsearch in Docker, but to run the Inventaire server and client outside. For this you will need to:
- have [NodeJS](https://nodejs.org/) >= v16 installed on your machine, which should make both `node` and `npm` executables accessible in your terminal
Then you can start CouchDB and Elasticsearch in the background
```sh
docker-compose up couchdb elasticsearch -d
```
Start the Inventaire server in development mode
```sh
cd inventaire
npm run watch
```
And in another terminal, start the client Webpack dev server
```sh
cd inventaire/client
npm run watch
```
General tips on how to run Inventaire can be found in the [server repository docs](https://git.inventaire.io/inventaire/tree/main/docs).
## Troubleshooting
### Elasticsearch errors
- `max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]`: fix by running the command `sudo sysctl -w vm.max_map_count=262144` on your host machine
See also [Elasticsearch with Docker](https://www.elastic.co/guide/en/elasticsearch/reference/7.9/docker.html)
### Quieting CouchDB notice
CouchDB may warn constantly that `_users` database does not exist, [as documented](https://docs.couchdb.org/en/latest/setup/single-node.html), you can create de database with:
`curl -X PUT http://127.0.0.1:5984/_users`

View File

@@ -1,6 +0,0 @@
; CouchDB configuration file, named to have a lower priority than ./docker.ini
; See https://docs.couchdb.org/en/stable/config/index.html
[fabric]
; Prevent "No DB shards could be opened" errors, see https://github.com/apache/couchdb/issues/4497
shard_timeout_min_msec = 5000

View File

@@ -0,0 +1,5 @@
FROM couchdb:3.4.2
COPY local.ini /opt/couchdb/etc/local.d/local.ini
# Inherit ENTRYPOINT and CMD from couchdb image

8
couchdb/local.ini Normal file
View File

@@ -0,0 +1,8 @@
[couchdb]
; Automatically create the system databases on startup (in particular `_users`)
; see https://docs.couchdb.org/en/stable/config/couchdb.html#couchdb/single_node
single_node = true
[fabric]
; Prevent "No DB shards could be opened" errors, see https://github.com/apache/couchdb/issues/4497
shard_timeout_min_msec = 5000

View File

@@ -1,28 +1,86 @@
version: '3'
services:
inventaire:
image: inventaire/inventaire:latest
env_file: .env
# You may also build image from sources with:
# build:
# context: ./inventaire
# dockerfile: Dockerfile.inventaire
depends_on:
- couchdb
- elasticsearch
# Uncomment if you want to access the code:
volumes:
- inventaire-server:/opt/inventaire
logging:
options:
max-size: "10m"
max-file: "3"
restart: unless-stopped
couchdb:
image: couchdb:3.4.2
ports:
- "5984:5984"
environment:
COUCHDB_USER: "yourcouchdbusername"
COUCHDB_PASSWORD: "yourcouchdbpassword"
build:
context: ./couchdb
dockerfile: Dockerfile.couchdb
env_file: .env
# Uncomment ports to get access to the db
# ie. for database transformation, querying, UI access (http://localhost:5984/_utils/)
# /!\ Beware that exposing container ports like this might bypass your firewall rules
# See https://docs.docker.com/engine/install/ubuntu/#firewall-limitations
# Keeping it bound to localhost (which is the default) should be safe though
# (that is, contrary to binding to 0.0.0.0)
# ports:
# - "5984:5984"
volumes:
- 'couchdb:/opt/couchdb/data'
- './configs:/opt/couchdb/etc/local.d'
tty: true
restart: unless-stopped
elasticsearch:
image: elasticsearch:7.16.2
image: elasticsearch:7.17.28
environment:
- 'http.host=0.0.0.0'
- 'transport.host=127.0.0.1'
- 'http.host=elasticsearch'
- 'transport.host=elasticsearch'
# See https://www.elastic.co/guide/en/elasticsearch/reference/7.16/docker.html
- 'discovery.type=single-node'
- 'ES_JAVA_OPTS=-Xms1g -Xmx1g'
# Limit memory usage to 512MB, that should be enough at first
# See https://www.elastic.co/guide/en/elasticsearch/reference/current/advanced-configuration.html
- 'ES_JAVA_OPTS=-Xms512m -Xmx512m'
- 'xpack.security.enabled=false'
- 'ingest.geoip.downloader.enabled=false'
- 'logger.org.elasticsearch=ERROR'
- 'logger.com.azure.core=ERROR'
- 'logger.org.apache=ERROR'
volumes:
- 'elasticsearch:/usr/share/elasticsearch/data'
ports :
- '127.0.0.1:9200:9200'
restart: unless-stopped
nginx:
build:
context: ./nginx
dockerfile: Dockerfile.nginx
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/templates:/etc/nginx/templates/
- ./nginx/snippets:/etc/nginx/snippets
- inventaire-server:/opt/inventaire
- certbot-www:/var/www/certbot
- ./certbot/conf:/etc/letsencrypt
env_file: .env
depends_on:
# Required to be able to define the `inventaire` host as an upstream
- inventaire
restart: unless-stopped
certbot:
image: certbot/certbot:latest
volumes:
- ./certbot/conf:/etc/letsencrypt
- certbot-www:/var/www/certbot
restart: unless-stopped
entrypoint: /bin/sh -c "trap exit TERM; while :; do certbot renew --webroot -w /var/www/certbot; sleep 12h & wait $${!}; done;"
depends_on:
- nginx
volumes:
couchdb:
elasticsearch:
certbot-www:
inventaire-server:

53
dotenv Normal file
View File

@@ -0,0 +1,53 @@
# Your website domain name
PUBLIC_HOSTNAME=an-inventaire-site.org
# Generic user, to modify only for good reason
COUCHDB_USER=couchdb
# Consider passwords with no less than 32 charracters, for example:
# cat /dev/urandom | tr -dc A-Za-z0-9-_ | head -c 32
COUCHDB_PASSWORD=your_password
INSTANCE_NAME='My Inventaire Instance'
# Will be displayed on landing screen
ORG_NAME='Example Organization'
ORG_URL='https://inventaire.example.org'
# Users receiving emails from the instance can reply to this
CONTACT_ADDRESS='contact@inventaire.example.org'
MAILER_SMTP_HOST=smtp.example.org
MAILER_SMTP_PORT=587
MAILER_SMTP_USERNAME=your_username_on_smtp.example.org
MAILER_SMTP_PASSWORD=your_password_on_smtp.example.org
# Required to use MapBox tiles within leaflet maps
# See https://console.mapbox.com/account/access-tokens/
MAP_TILES_ACCESS_TOKEN='youraccesstoken'
# [OPTIONAL] Setup Matomo analytics https://matomo.org/
MOTOMO_ENABLED=false
MOTOMO_ENDPOINT=https://yourmatomoendpoint/matomo.php
MOTOMO_IDSITE=1
MOTOMO_REC=1
MEDIA_STORAGE_MODE=local
# Set MEDIA_STORAGE_MODE=swift and the following variables
# to store users and groups images in an OpenStack Swift container
SWIFT_USERNAME=customizedInLocalConfig
SWIFT_PASSWORD=customizedInLocalConfig
SWIFT_AUTH_URL=https://openstackEndpointToCustomize
SWIFT_PUBLIC_URL=https://swiftPublicURL
SWIFT_TENANT_NAME=12345678
SWIFT_REGION=SBG-1
########
# Everything below is a default configuration
# Modify if you know what you are doing
########
NODE_ENV=production
NODE_APP_INSTANCE=federated
# Conventional port for Inventaire server in federated mode
INVENTAIRE_PORT=3016

View File

@@ -0,0 +1,39 @@
FROM node:20-slim
RUN apt-get update \
&& apt-get install -y curl git graphicsmagick inotify-tools jq \
&& apt-get clean && rm -rf /var/lib/apt/lists/* \
&& mkdir -p /opt/inventaire \
&& chown -R 1000:1000 /opt
# Default to the same user as the host (override from command line if needed)
# Known benefits:
# - allows to handle leveldb with level-party from both the host and container at the same time
USER 1000:1000
WORKDIR /opt/inventaire
# - Create the client folder to prevent the server postinstall to run `npm run install-client` as it does it with the wrong workdir and env
# - Create the public/sitemaps folder to prevent the client postinstall to run `npm run generate-sitemaps` (which needs to be updated to support non-inventaire.io instances)
RUN git clone http://github.com/inventaire/inventaire --depth 1 . \
&& mkdir -p /opt/inventaire/client \
&& npm ci --omit=dev \
&& npm run build \
&& git clone https://git.inventaire.io/inventaire-client.git ./client --branch docker --depth 1 \
&& mkdir -p /opt/inventaire/client/public/sitemaps
WORKDIR /opt/inventaire/client
# Include dev dependencies (webpack, svelte-checks) at first to be able to build during the postinstall script
RUN npm ci \
&& rm -rf node_modules \
&& npm ci --omit=dev --ignore-scripts \
&& npm cache clean --force
COPY docker-entrypoint.sh /opt/docker-entrypoint.sh
WORKDIR /opt/inventaire
# Avoid using npm script to start the server
# See https://adambrodziak.pl/dockerfile-good-practices-for-node-and-npm#heading-use-node-not-npm-to-start-the-server
ENTRYPOINT [ "/opt/docker-entrypoint.sh" ]

61
inventaire/docker-entrypoint.sh Executable file
View File

@@ -0,0 +1,61 @@
#!/usr/bin/env bash
set -eu
cd /opt/inventaire
# Overwrites the local config with environment variables every time the container is restarted
# This file can be itself overwritten either by ./config/local-production.cjs (assuming NODE_ENV=production) or by NODE_CONFIG
# See https://github.com/node-config/node-config/wiki/Configuration-Files#file-load-order
# and https://github.com/node-config/node-config/wiki/Environment-Variables#node_config
cat > "./config/local.cjs" << EOF
module.exports = {
hostname: 'inventaire',
port: '${INVENTAIRE_PORT}',
publicHostname: '${PUBLIC_HOSTNAME}',
instanceName: '${INSTANCE_NAME}',
orgName: '${ORG_NAME}',
orgUrl: '${ORG_URL}',
contactAddress: '${CONTACT_ADDRESS}',
db: {
username: '${COUCHDB_USER}',
password: '${COUCHDB_PASSWORD}',
hostname: 'couchdb',
},
elasticsearch: {
origin: 'http://elasticsearch:9200',
},
mailer: {
disabled: false,
nodemailer: {
host: '${MAILER_SMTP_HOST}',
port: ${MAILER_SMTP_PORT},
auth: {
user: '${MAILER_SMTP_USERNAME}',
pass: '${MAILER_SMTP_PASSWORD}'
},
},
},
mapTilesAccessToken: '${MAP_TILES_ACCESS_TOKEN}',
matomo: {
enabled: ${MOTOMO_ENABLED},
endpoint: '${MOTOMO_ENDPOINT}',
idsite: ${MOTOMO_IDSITE},
rec: ${MOTOMO_REC},
},
mediaStorage: {
mode: '${MEDIA_STORAGE_MODE}',
swift: {
username: '${SWIFT_USERNAME}',
password: '${SWIFT_PASSWORD}',
authUrl: '${SWIFT_AUTH_URL}',
publicURL: '${SWIFT_PUBLIC_URL}',
tenantName: '${SWIFT_TENANT_NAME}',
region: '${SWIFT_REGION}',
},
},
}
EOF
./scripts/typescript/start_built_server.sh

5
nginx/Dockerfile.nginx Normal file
View File

@@ -0,0 +1,5 @@
FROM nginx
RUN [ ! -f /etc/nginx/dhparam.pem ] && openssl dhparam -out /etc/nginx/dhparam.pem 2048
RUN mkdir -p /tmp/nginx/tmp /tmp/nginx/resize/img/users /tmp/nginx/resize/img/groups /tmp/nginx/resize/img/entities /tmp/nginx/resize/img/remote /tmp/nginx/resize/img/assets && chown -R nginx:nginx /tmp/nginx

View File

@@ -0,0 +1,12 @@
# add_header from parent blocks are ignored when the current block also calls add_header
# Thus the need for this snippet, to redefine the same headers in many blocks
# See http://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# opt out Google Floc see: https://plausible.io/blog/google-floc#how-to-opt-out-of-floc-as-a-web-developer-set-a-permissions-policy
add_header Permissions-Policy interest-cohort=();
# source: https://gist.github.com/plentz/6737338
add_header X-Frame-Options "SAMEORIGIN" always;
# source: https://scotthelme.co.uk/hardening-your-http-response-headers/#x-content-type-options
add_header X-Content-Type-Options 'nosniff' always;
# source: https://scotthelme.co.uk/a-new-security-header-referrer-policy/
add_header Referrer-Policy 'strict-origin' always;

11
nginx/snippets/ssl.conf Normal file
View File

@@ -0,0 +1,11 @@
# Recommended by https://ssl-config.mozilla.org/#server=nginx&version=1.18.0&config=intermediate&openssl=1.1.1f&guideline=5.6
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers on;
ssl_stapling on;
ssl_stapling_verify on;
ssl_dhparam /etc/nginx/dhparam.pem;

View File

@@ -0,0 +1,207 @@
# The INVENTAIRE_PORT and PUBLIC_HOSTNAME variables are set with nginx image function,
# which will extract environment variables before nginx starts
# See https://hub.docker.com/_/nginx
upstream inv {
server inventaire:${INVENTAIRE_PORT} fail_timeout=5s;
}
# Using error_page as a way to have a named location that can
# then be shared between several locations, see:
# https://serverfault.com/questions/908086/nginx-directly-send-from-location-to-another-named-location
# https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil/#what-to-do-instead
# Contrary to what the documentation says, the HTTP verbs aren't all converted to GET
# http://nginx.org/en/docs/http/ngx_http_core_module.html#error_page
error_page 543 = @invserver;
server {
listen 80;
listen [::]:80;
# Required to be able to run `certbot -w /var/www/html/`
location /.well-known/ {
root /var/www/html/;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name ${PUBLIC_HOSTNAME};
ssl_certificate /etc/letsencrypt/live/${PUBLIC_HOSTNAME}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${PUBLIC_HOSTNAME}/privkey.pem;
include /etc/nginx/snippets/ssl.conf;
client_max_body_size 25M;
# Disabling compression to mitigate BREACH exploit
# https://en.wikipedia.org/wiki/BREACH_(security_exploit)#Mitigation
# http://security.stackexchange.com/questions/39925/breach-a-new-attack-against-http-what-can-be-done
# until we can confidently say that HTTP/2 solves the issue? https://blog.cloudflare.com/hpack-the-silent-killer-feature-of-http-2
gzip off;
# On-The-Fly Image Resizer
# URLs look like /img/users/300x1200/8185d4e039f52b4faa06a1c277133e9a8232551b
# for locally hosted images
# or /img/remote/300x1200/630022006?href=http%3A%2F%2Fescaped.url
# for remote images, with 630022006 being the hash of the passed href
# generated by [hashCode](https://git.inventaire.io/inventaire/blob/35b1e63/server/lib/utils/base.js#L69-L80)
# The hack: I couldn't make the proxy_store work: it never hits the cache, but
# it does put the resized images in /tmp/nginx/resize, so using a try_files
# directive instead
# Sometimes, for some unidentified reason, the cached files end up empty, so it can be useful to add a root cron to remove those files:
# 0 4 * * * /usr/bin/find /tmp/nginx -type f -size 0 -delete
# Do not remove the (.*) capture group as it seems to be required by the try_files
location ~ ^/img/(groups|users|entities|assets)/(.*) {
include /etc/nginx/snippets/security_headers.conf;
root /tmp/nginx/resize;
default_type "image/jpeg";
add_header Cache-Control "public, max-age=31536000, immutable";
add_header X-File-Cache "hit";
add_header Content-Security-Policy "sandbox";
try_files $uri @invimg;
limit_except GET {
deny all;
}
}
# Same as above, but without the immutable
location ~ ^/img/remote/(.*) {
include /etc/nginx/snippets/security_headers.conf;
root /tmp/nginx/resize;
default_type "image/jpeg";
add_header X-File-Cache "hit";
add_header Content-Security-Policy "sandbox";
try_files $uri @invimg;
limit_except GET {
deny all;
}
}
location ~ ^/img/ {
return 404;
}
location @invimg {
include /etc/nginx/snippets/security_headers.conf;
default_type "image/jpeg";
# add_header Content-Type "image/jpeg";
add_header X-File-Cache "miss";
add_header Content-Security-Policy "sandbox";
proxy_temp_path /tmp/nginx/tmp;
proxy_store /tmp/nginx/resize$uri;
proxy_store_access user:rw group:rw all:r;
proxy_http_version 1.1;
proxy_pass http://inv;
}
root /opt/inventaire/client;
location /public {
include /etc/nginx/snippets/security_headers.conf;
limit_except GET {
deny all;
}
gzip_static on;
# Let resources that can't be cache busted
# - such as opensearch.xml or robots.txt -
# out of this caching policy
if ($uri ~ "^/public/(dist|fonts)/" ) {
include /etc/nginx/snippets/security_headers.conf;
add_header Cache-Control "public, max-age=31536000, immutable";
# All headers that aren't in the last block won't be taken in account
# thus the need to have CORS headers here too
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET' always;
}
}
# Pass the request to the node.js server
# with some correct headers for proxy-awareness
location /api {
return 543;
}
location /.well-known/webfinger {
return 543;
}
# Let the API server handle all but /public JSON and RSS requests
location ~ "^/[^p].*\.(json|rss)$" {
limit_except GET {
deny all;
}
return 543;
}
location @invserver {
include /etc/nginx/snippets/security_headers.conf;
# Let the server decide when CORS headers should be added
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Host $host;
# Set a large value to let the API determine the appropriate
# timeout per endpoint
# http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_read_timeout
proxy_read_timeout 3600;
proxy_redirect off;
proxy_http_version 1.1;
proxy_pass http://inv;
}
location = /favicon.ico {
include /etc/nginx/snippets/security_headers.conf;
try_files /public/$uri /public/images/$uri;
expires 30d;
add_header Cache-Control "public";
}
location = /robots.txt {
include /etc/nginx/snippets/security_headers.conf;
gzip_static on;
try_files /public/$uri /$uri;
expires 1d;
add_header Cache-Control "public";
}
# Prevent exposing git folders such as /public/i18n/.git
# For why this rule takes precedence over location /public/
# see http://stackoverflow.com/a/34262192/3324977
location ~ /\.git {
deny all;
}
location ^~ '/.well-known/acme-challenge' {
include /etc/nginx/snippets/security_headers.conf;
default_type "text/plain";
root /var/www/certbot;
}
location / {
include /etc/nginx/snippets/security_headers.conf;
gzip_static on;
limit_except GET {
deny all;
}
# index.html should always be fresh out of the server
# time is negative => “Cache-Control: no-cache”
# http://nginx.org/en/docs/http/ngx_http_headers_module.html
# Those headers should be set here and not at "location /" as they would be ignored (cf http://serverfault.com/a/786248)
expires -1;
# The remaining routes (/users, /entity, etc) should be handled by the client router
rewrite .* /public/index.html break;
}
}

20
scripts/docker_publish.sh Executable file
View File

@@ -0,0 +1,20 @@
#!/usr/bin/env bash
set -eu
cwd="$PWD"
cd ./inventaire
echo -n "Enter version number (ex: 3.0.0-beta): "
read -r version
docker build -t inventaire -f ./Dockerfile.inventaire .
docker tag inventaire "inventaire/inventaire:${version}"
docker tag inventaire inventaire/inventaire:latest
docker push "inventaire/inventaire:${version}"
docker push inventaire/inventaire:latest
cd "$cwd"