Browse Source
Feature/harden container security following OWASP best practices (#3614)
* Harden container security
* Update changelog
pull/3632/head
Nuno
6 months ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with
43 additions and
12 deletions
-
CHANGELOG.md
-
Dockerfile
-
docker/docker-compose.build.yml
-
docker/docker-compose.dev.yml
-
docker/docker-compose.yml
|
|
@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. |
|
|
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), |
|
|
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). |
|
|
|
|
|
|
|
## Unreleased |
|
|
|
|
|
|
|
### Changed |
|
|
|
|
|
|
|
- Hardened container security by switching to a non-root user, setting the filesystem to read-only, and dropping unnecessary capabilities |
|
|
|
|
|
|
|
## 2.100.0 - 2024-08-03 |
|
|
|
|
|
|
|
### Added |
|
|
|
|
|
@ -11,7 +11,7 @@ COPY ./package.json package.json |
|
|
|
COPY ./package-lock.json package-lock.json |
|
|
|
COPY ./prisma/schema.prisma prisma/schema.prisma |
|
|
|
|
|
|
|
RUN apt update && apt install -y \ |
|
|
|
RUN apt-get update && apt-get install -y --no-install-suggests \ |
|
|
|
g++ \ |
|
|
|
git \ |
|
|
|
make \ |
|
|
@ -50,16 +50,18 @@ RUN npm run database:generate-typings |
|
|
|
|
|
|
|
# Image to run, copy everything needed from builder |
|
|
|
FROM node:20-slim |
|
|
|
|
|
|
|
LABEL org.opencontainers.image.source="https://github.com/ghostfolio/ghostfolio" |
|
|
|
ENV NODE_ENV=production |
|
|
|
|
|
|
|
RUN apt update && apt install -y \ |
|
|
|
RUN apt-get update && apt-get install -y --no-install-suggests \ |
|
|
|
curl \ |
|
|
|
openssl \ |
|
|
|
&& rm -rf /var/lib/apt/lists/* |
|
|
|
|
|
|
|
COPY --from=builder /ghostfolio/dist/apps /ghostfolio/apps |
|
|
|
COPY ./docker/entrypoint.sh /ghostfolio/entrypoint.sh |
|
|
|
RUN chown -R node:node /ghostfolio |
|
|
|
WORKDIR /ghostfolio/apps/api |
|
|
|
EXPOSE ${PORT:-3333} |
|
|
|
USER node |
|
|
|
CMD [ "/ghostfolio/entrypoint.sh" ] |
|
|
|
|
|
@ -6,7 +6,6 @@ services: |
|
|
|
- ../.env |
|
|
|
environment: |
|
|
|
DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?connect_timeout=300&sslmode=prefer |
|
|
|
NODE_ENV: production |
|
|
|
REDIS_HOST: redis |
|
|
|
REDIS_PASSWORD: ${REDIS_PASSWORD} |
|
|
|
ports: |
|
|
@ -21,8 +20,9 @@ services: |
|
|
|
interval: 10s |
|
|
|
timeout: 5s |
|
|
|
retries: 5 |
|
|
|
|
|
|
|
postgres: |
|
|
|
image: postgres:15 |
|
|
|
image: docker.io/library/postgres:15 |
|
|
|
env_file: |
|
|
|
- ../.env |
|
|
|
healthcheck: |
|
|
@ -32,8 +32,9 @@ services: |
|
|
|
retries: 5 |
|
|
|
volumes: |
|
|
|
- postgres:/var/lib/postgresql/data |
|
|
|
|
|
|
|
redis: |
|
|
|
image: redis:alpine |
|
|
|
image: docker.io/library/redis:alpine |
|
|
|
env_file: |
|
|
|
- ../.env |
|
|
|
command: ['redis-server', '--requirepass', $REDIS_PASSWORD] |
|
|
|
|
|
@ -1,6 +1,6 @@ |
|
|
|
services: |
|
|
|
postgres: |
|
|
|
image: postgres:15 |
|
|
|
image: docker.io/library/postgres:15 |
|
|
|
container_name: postgres |
|
|
|
restart: unless-stopped |
|
|
|
env_file: |
|
|
@ -9,8 +9,9 @@ services: |
|
|
|
- ${POSTGRES_PORT:-5432}:5432 |
|
|
|
volumes: |
|
|
|
- postgres:/var/lib/postgresql/data |
|
|
|
|
|
|
|
redis: |
|
|
|
image: redis:alpine |
|
|
|
image: docker.io/library/redis:alpine |
|
|
|
container_name: redis |
|
|
|
restart: unless-stopped |
|
|
|
env_file: |
|
|
|
|
|
@ -1,12 +1,16 @@ |
|
|
|
services: |
|
|
|
ghostfolio: |
|
|
|
image: ghostfolio/ghostfolio:latest |
|
|
|
image: docker.io/ghostfolio/ghostfolio:latest |
|
|
|
init: true |
|
|
|
read_only: true |
|
|
|
cap_drop: |
|
|
|
- ALL |
|
|
|
security_opt: |
|
|
|
- no-new-privileges:true |
|
|
|
env_file: |
|
|
|
- ../.env |
|
|
|
environment: |
|
|
|
DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?connect_timeout=300&sslmode=prefer |
|
|
|
NODE_ENV: production |
|
|
|
REDIS_HOST: redis |
|
|
|
REDIS_PASSWORD: ${REDIS_PASSWORD} |
|
|
|
ports: |
|
|
@ -21,8 +25,19 @@ services: |
|
|
|
interval: 10s |
|
|
|
timeout: 5s |
|
|
|
retries: 5 |
|
|
|
|
|
|
|
postgres: |
|
|
|
image: postgres:15 |
|
|
|
image: docker.io/library/postgres:15 |
|
|
|
cap_drop: |
|
|
|
- ALL |
|
|
|
cap_add: |
|
|
|
- CHOWN |
|
|
|
- DAC_READ_SEARCH |
|
|
|
- FOWNER |
|
|
|
- SETGID |
|
|
|
- SETUID |
|
|
|
security_opt: |
|
|
|
- no-new-privileges:true |
|
|
|
env_file: |
|
|
|
- ../.env |
|
|
|
healthcheck: |
|
|
@ -32,8 +47,14 @@ services: |
|
|
|
retries: 5 |
|
|
|
volumes: |
|
|
|
- postgres:/var/lib/postgresql/data |
|
|
|
|
|
|
|
redis: |
|
|
|
image: redis:alpine |
|
|
|
image: docker.io/library/redis:alpine |
|
|
|
user: '999:1000' |
|
|
|
cap_drop: |
|
|
|
- ALL |
|
|
|
security_opt: |
|
|
|
- no-new-privileges:true |
|
|
|
env_file: |
|
|
|
- ../.env |
|
|
|
command: ['redis-server', '--requirepass', $REDIS_PASSWORD] |
|
|
|