migrate to nginx-unprivileged for enhanced security
This commit is contained in:
24
Dockerfile
24
Dockerfile
@@ -15,24 +15,18 @@ ENV SIMPLE_MODE=$SIMPLE_MODE
|
|||||||
RUN npm run build -- --mode production
|
RUN npm run build -- --mode production
|
||||||
|
|
||||||
# Production stage
|
# Production stage
|
||||||
FROM nginx:alpine
|
FROM nginxinc/nginx-unprivileged:1.29-alpine
|
||||||
|
|
||||||
ARG APP_USER_ID=1001
|
|
||||||
ARG APP_GROUP_ID=1001
|
|
||||||
|
|
||||||
RUN addgroup -g $APP_GROUP_ID bentopdf && \
|
|
||||||
adduser -u $APP_USER_ID -G bentopdf -D -s /bin/sh bentopdf
|
|
||||||
|
|
||||||
|
# Copy files as root first, then change ownership
|
||||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||||
COPY nginx.conf /etc/nginx/nginx.conf
|
COPY nginx.conf /etc/nginx/nginx.conf
|
||||||
|
|
||||||
RUN mkdir -p /var/cache/nginx /var/log/nginx /var/run/nginx && \
|
# Change ownership while still root, then switch to nginx user
|
||||||
chown -R bentopdf:bentopdf /usr/share/nginx/html /var/cache/nginx /var/log/nginx /var/run/nginx
|
USER root
|
||||||
|
RUN mkdir -p /etc/nginx/tmp && \
|
||||||
|
chown -R nginx:nginx /usr/share/nginx/html /etc/nginx/tmp
|
||||||
|
USER nginx
|
||||||
|
|
||||||
RUN sed -i 's/user nginx;/user bentopdf;/' /etc/nginx/nginx.conf
|
EXPOSE 8080
|
||||||
|
|
||||||
EXPOSE 80
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
|
|
||||||
USER bentopdf
|
|
||||||
|
|
||||||
CMD ["nginx", "-g", "daemon off;"]
|
|
||||||
|
|||||||
20
README.md
20
README.md
@@ -105,7 +105,7 @@ You can run BentoPDF locally for development or personal use.
|
|||||||
You can run BentoPDF directly from Docker Hub without cloning the repository:
|
You can run BentoPDF directly from Docker Hub without cloning the repository:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker run -p 3000:80 bentopdf/bentopdf:latest
|
docker run -p 3000:8080 bentopdf/bentopdf:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
Open your browser at: http://localhost:3000
|
Open your browser at: http://localhost:3000
|
||||||
@@ -124,7 +124,7 @@ services:
|
|||||||
image: bentopdf/bentopdf:latest
|
image: bentopdf/bentopdf:latest
|
||||||
container_name: bentopdf
|
container_name: bentopdf
|
||||||
ports:
|
ports:
|
||||||
- '3000:80'
|
- '3000:8080'
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -151,21 +151,17 @@ For more details, see [SIMPLE_MODE.md](SIMPLE_MODE.md).
|
|||||||
|
|
||||||
### 🔒 Security Features
|
### 🔒 Security Features
|
||||||
|
|
||||||
BentoPDF runs as a non-root user for enhanced security:
|
BentoPDF runs as a non-root user using nginx-unprivileged for enhanced security:
|
||||||
|
|
||||||
- **Non-Root Execution**: Container runs with minimal privileges
|
- **Non-Root Execution**: Container runs with minimal privileges using nginx-unprivileged
|
||||||
- **Configurable UID/GID**: Customize user/group IDs for your environment
|
- **Port 8080**: Uses high port number to avoid requiring root privileges
|
||||||
- **Security Best Practices**: Follows Principle of Least Privilege
|
- **Security Best Practices**: Follows Principle of Least Privilege
|
||||||
|
|
||||||
#### Custom User Configuration
|
#### Basic Usage
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker build \
|
docker build -t bentopdf .
|
||||||
--build-arg APP_USER_ID=2000 \
|
docker run -p 8080:8080 bentopdf
|
||||||
--build-arg APP_GROUP_ID=2000 \
|
|
||||||
-t bentopdf .
|
|
||||||
|
|
||||||
docker run -p 8080:80 bentopdf
|
|
||||||
```
|
```
|
||||||
|
|
||||||
For detailed security configuration, see [SECURITY.md](SECURITY.md).
|
For detailed security configuration, see [SECURITY.md](SECURITY.md).
|
||||||
|
|||||||
50
SECURITY.md
50
SECURITY.md
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## Non-Root User Support
|
## Non-Root User Support
|
||||||
|
|
||||||
BentoPDF now supports running as a non-root user for enhanced security. This follows the Principle of Least Privilege and is essential for production environments.
|
BentoPDF now uses nginx-unprivileged for enhanced security. This follows the Principle of Least Privilege and is essential for production environments.
|
||||||
|
|
||||||
### Security Benefits
|
### Security Benefits
|
||||||
|
|
||||||
@@ -13,22 +13,19 @@ BentoPDF now supports running as a non-root user for enhanced security. This fol
|
|||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
|
|
||||||
#### Default Configuration (UID/GID 1001)
|
#### Default Configuration (nginx-unprivileged)
|
||||||
```bash
|
```bash
|
||||||
docker build -t bentopdf .
|
docker build -t bentopdf .
|
||||||
docker run -p 8080:80 bentopdf
|
docker run -p 8080:8080 bentopdf
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Custom UID/GID
|
#### Simple Mode
|
||||||
```bash
|
```bash
|
||||||
# Build with custom user/group IDs
|
# Build with simple mode enabled
|
||||||
docker build \
|
docker build --build-arg SIMPLE_MODE=true -t bentopdf-simple .
|
||||||
--build-arg APP_USER_ID=2000 \
|
|
||||||
--build-arg APP_GROUP_ID=2000 \
|
|
||||||
-t bentopdf .
|
|
||||||
|
|
||||||
# Run the container
|
# Run the container
|
||||||
docker run -p 8080:80 bentopdf
|
docker run -p 8080:8080 bentopdf-simple
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Kubernetes Example
|
#### Kubernetes Example
|
||||||
@@ -48,7 +45,7 @@ spec:
|
|||||||
- name: bentopdf
|
- name: bentopdf
|
||||||
image: bentopdf:latest
|
image: bentopdf:latest
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 80
|
- containerPort: 8080
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Docker Compose Example
|
#### Docker Compose Example
|
||||||
@@ -60,10 +57,9 @@ services:
|
|||||||
context: .
|
context: .
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
args:
|
args:
|
||||||
APP_USER_ID: 2000
|
SIMPLE_MODE: false
|
||||||
APP_GROUP_ID: 2000
|
|
||||||
ports:
|
ports:
|
||||||
- "8080:80"
|
- "8080:8080"
|
||||||
security_opt:
|
security_opt:
|
||||||
- no-new-privileges:true
|
- no-new-privileges:true
|
||||||
```
|
```
|
||||||
@@ -75,18 +71,18 @@ To verify the container is running as non-root:
|
|||||||
```bash
|
```bash
|
||||||
# Check the user inside the container
|
# Check the user inside the container
|
||||||
docker exec <container_id> whoami
|
docker exec <container_id> whoami
|
||||||
# Should output: bentopdf
|
# Should output: nginx
|
||||||
|
|
||||||
# Check the user ID
|
# Check the user ID
|
||||||
docker exec <container_id> id
|
docker exec <container_id> id
|
||||||
# Should show UID/GID matching your configuration
|
# Should show UID/GID for nginx user (typically 101)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Security Best Practices
|
### Security Best Practices
|
||||||
|
|
||||||
1. **Use specific UID/GID**: Don't use 0 (root) or common system UIDs
|
1. **Use nginx-unprivileged**: Built-in non-root user with minimal privileges
|
||||||
2. **Regular Updates**: Keep the base image updated
|
2. **Regular Updates**: Keep the base image updated (currently using 1.29-alpine)
|
||||||
3. **Minimal Permissions**: Only grant necessary file permissions
|
3. **Port 8080**: Use high port numbers to avoid requiring root privileges
|
||||||
4. **Security Scanning**: Regularly scan images for vulnerabilities
|
4. **Security Scanning**: Regularly scan images for vulnerabilities
|
||||||
5. **Network Policies**: Implement network segmentation
|
5. **Network Policies**: Implement network segmentation
|
||||||
|
|
||||||
@@ -94,15 +90,17 @@ docker exec <container_id> id
|
|||||||
|
|
||||||
If you encounter permission issues:
|
If you encounter permission issues:
|
||||||
|
|
||||||
1. **Check file ownership**: Ensure all application files are owned by the bentopdf user
|
1. **Check file ownership**: Ensure all application files are owned by the nginx user
|
||||||
2. **Verify UID/GID**: Make sure the configured IDs don't conflict with host system
|
2. **Verify PID directory**: Ensure `/etc/nginx/tmp/` directory exists and is writable
|
||||||
3. **Directory permissions**: Ensure nginx can write to log and cache directories
|
3. **Port binding**: Ensure port 8080 is available and not blocked by firewall
|
||||||
|
|
||||||
### Migration from Root
|
### Migration from Root
|
||||||
|
|
||||||
If migrating from a root-based setup:
|
If migrating from a root-based setup:
|
||||||
|
|
||||||
1. Update your Dockerfile to use the new non-root configuration
|
1. Update your Dockerfile to use nginx-unprivileged base image
|
||||||
2. Rebuild your images with the new security settings
|
2. Change port mappings from 80 to 8080 in all configurations
|
||||||
3. Update your deployment configurations (Kubernetes, Docker Compose, etc.)
|
3. Update nginx.conf to use `/etc/nginx/tmp/nginx.pid` for PID file
|
||||||
4. Test thoroughly in a staging environment
|
4. Rebuild your images with the new security settings
|
||||||
|
5. Update your deployment configurations (Kubernetes, Docker Compose, etc.)
|
||||||
|
6. Test thoroughly in a staging environment
|
||||||
|
|||||||
@@ -4,10 +4,8 @@ services:
|
|||||||
context: .
|
context: .
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
args:
|
args:
|
||||||
APP_USER_ID: 1001 // default value is 1001 can be customized to any other value
|
SIMPLE_MODE: true # false for default mode, true for simple mode
|
||||||
APP_GROUP_ID: 1001 // default value is 1001 can be customized to any other value
|
|
||||||
SIMPLE_MODE: false // false for default mode, true for simple mode
|
|
||||||
container_name: bentopdf
|
container_name: bentopdf
|
||||||
ports:
|
ports:
|
||||||
- '3000:80'
|
- '3000:8080'
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|||||||
@@ -6,4 +6,4 @@ services:
|
|||||||
container_name: bentopdf
|
container_name: bentopdf
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
- '3000:80'
|
- '3000:8080'
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
pid /var/run/nginx/nginx.pid;
|
pid /etc/nginx/tmp/nginx.pid;
|
||||||
|
|
||||||
events {
|
events {
|
||||||
worker_connections 1024;
|
worker_connections 1024;
|
||||||
@@ -17,7 +17,7 @@ http {
|
|||||||
gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json;
|
gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json;
|
||||||
|
|
||||||
server {
|
server {
|
||||||
listen 80;
|
listen 8080;
|
||||||
server_name localhost;
|
server_name localhost;
|
||||||
root /usr/share/nginx/html;
|
root /usr/share/nginx/html;
|
||||||
index index.html;
|
index index.html;
|
||||||
|
|||||||
Reference in New Issue
Block a user