Update docker setup to run under HTTPS by default (#364)

This commit is contained in:
Leendert de Borst
2024-11-15 11:55:26 +01:00
parent 3d24772caa
commit df6de32a4a
12 changed files with 147 additions and 31 deletions

4
.gitignore vendored
View File

@@ -393,3 +393,7 @@ src/Tests/AliasVault.E2ETests/appsettings.Development.json
# Draw.io diagram temp files
*.drawio.*
# Certificates
certificates/*.crt
certificates/*.key
certificates/*.pfx

View File

@@ -1,4 +1,6 @@
This is the default location where (self-generated) certificates are stored.
# Certificates directory structure
For example, the API and Admin projects make use of the .NET DataProtection API that depends on
certificates for encrypting various types of application data such as authentication cookies, anti-forgery tokens etc.
This directory contains certificates for AliasVault.
- `app`: Certificates that AliasVault uses to protect application data at rest (e.g. .NET DataProtection keys)
- `ssl`: SSL/TLS certificates for AliasVault hosted services

View File

@@ -0,0 +1,7 @@
# SSL certificates directory structure
This directory contains SSL/TLS certificates for various AliasVault services:
- `admin`: Certificate for the Admin UI.
- `api`: Certificate for the API service.
- `client`: Certificate for the Client UI.

View File

@@ -5,21 +5,26 @@ services:
context: .
dockerfile: src/AliasVault.Admin/Dockerfile
ports:
- "8080:8082"
- "4431:4431"
volumes:
- ./certificates:/certificates:rw
- ./certificates/app:/certificates:rw
- ./certificates/ssl/admin:/app/ssl:rw
- ./database:/database:rw
- ./logs:/logs:rw
restart: always
env_file:
- .env
client:
image: aliasvault-client
build:
context: .
dockerfile: src/AliasVault.Client/Dockerfile
ports:
- "80:8080"
- "80:80"
- "443:443"
volumes:
- ./certificates/ssl/client:/etc/nginx/ssl:rw
restart: always
env_file:
- .env
@@ -30,9 +35,10 @@ services:
context: .
dockerfile: src/AliasVault.Api/Dockerfile
ports:
- "81:8081"
- "4430:4430"
volumes:
- ./certificates:/certificates:rw
- ./certificates/app:/certificates:rw
- ./certificates/ssl/api:/app/ssl:rw
- ./database:/database:rw
- ./logs:/logs:rw
env_file:

View File

@@ -140,11 +140,11 @@ create_env_file() {
fi
}
# Function to check and populate the .env file with API_URL
# Function to populate API_URL
populate_api_url() {
printf "${CYAN}> Checking API_URL...${NC}\n"
if ! grep -q "^API_URL=" "$ENV_FILE" || [ -z "$(grep "^API_URL=" "$ENV_FILE" | cut -d '=' -f2)" ]; then
DEFAULT_API_URL="http://localhost:81"
DEFAULT_API_URL="https://localhost:4430"
read -p "Enter the base URL where the API will be hosted (press Enter for default: $DEFAULT_API_URL): " USER_API_URL
API_URL=${USER_API_URL:-$DEFAULT_API_URL}
if grep -q "^API_URL=" "$ENV_FILE"; then
@@ -381,14 +381,14 @@ main() {
printf "${CYAN}To configure the server, login to the admin panel:${NC}\n"
printf "\n"
if [ "$ADMIN_PASSWORD" != "" ]; then
printf "Admin Panel: http://localhost:8080/\n"
printf "Admin Panel: https://localhost:4431/\n"
printf "Username: admin\n"
printf "Password: $ADMIN_PASSWORD\n"
printf "\n"
printf "${YELLOW}(!) Caution: Make sure to backup the above credentials in a safe place, they won't be shown again!${NC}\n"
printf "\n"
else
printf "Admin Panel: http://localhost:8080/\n"
printf "Admin Panel: https://localhost:4431/\n"
printf "Username: admin\n"
printf "Password: (Previously set. Run this command with --reset-password to generate a new one.)\n"
printf "\n"
@@ -397,7 +397,8 @@ main() {
printf "\n"
printf "${CYAN}In order to start using AliasVault and create your own vault, log into the client website:${NC}\n"
printf "\n"
printf "Client Website: http://localhost:80/\n"
printf "Client Website: https://localhost:443/\n"
printf "${YELLOW}Note: The client website will automatically redirect from HTTP (port 80) to HTTPS (port 443)${NC}\n"
printf "You can create your own account from there.\n"
printf "\n"
printf "${MAGENTA}=========================================================${NC}\n"

View File

@@ -1,6 +1,6 @@
FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base
WORKDIR /app
EXPOSE 8082
EXPOSE 4431
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
ARG BUILD_CONFIGURATION=Release
@@ -24,6 +24,12 @@ RUN dotnet publish "AliasVault.Admin.csproj" -c "$BUILD_CONFIGURATION" -o /app/p
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
EXPOSE 8082
ENV ASPNETCORE_URLS=http://+:8082
ENTRYPOINT ["dotnet", "AliasVault.Admin.dll"]
COPY /src/AliasVault.Admin/entrypoint.sh /app
# Create SSL directory
RUN mkdir -p /app/ssl && chmod 755 /app/ssl
RUN chmod +x /app/entrypoint.sh
EXPOSE 4431
ENV ASPNETCORE_URLS=https://+:4431
ENTRYPOINT ["/app/entrypoint.sh"]

View File

@@ -0,0 +1,29 @@
#!/bin/sh
# Create SSL directory if it doesn't exist
mkdir -p /app/ssl
# Generate self-signed SSL certificate if not exists
if [ ! -f /app/ssl/admin.crt ] || [ ! -f /app/ssl/admin.key ]; then
echo "Generating new SSL certificate..."
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /app/ssl/admin.key \
-out /app/ssl/admin.crt \
-subj "/C=US/ST=State/L=City/O=Organization/CN=localhost"
# Set proper permissions
chmod 644 /app/ssl/admin.crt
chmod 600 /app/ssl/admin.key
# Create PFX for ASP.NET Core
openssl pkcs12 -export -out /app/ssl/admin.pfx \
-inkey /app/ssl/admin.key \
-in /app/ssl/admin.crt \
-password pass:YourSecurePassword
fi
export ASPNETCORE_Kestrel__Certificates__Default__Path=/app/ssl/admin.pfx
export ASPNETCORE_Kestrel__Certificates__Default__Password=YourSecurePassword
# Start the application
dotnet AliasVault.Admin.dll

View File

@@ -1,6 +1,6 @@
FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base
WORKDIR /app
EXPOSE 8081
EXPOSE 4430
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
ARG BUILD_CONFIGURATION=Release
@@ -16,7 +16,6 @@ COPY . .
WORKDIR "/src/src/AliasVault.Api"
RUN dotnet build "AliasVault.Api.csproj" -c "$BUILD_CONFIGURATION" -o /app/build
# Publish the application to the /app/publish directory in the container
FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "AliasVault.Api.csproj" -c "$BUILD_CONFIGURATION" -o /app/publish /p:UseAppHost=false
@@ -25,7 +24,11 @@ FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
COPY /src/AliasVault.Api/entrypoint.sh /app
# Create SSL directory
RUN mkdir -p /app/ssl && chmod 755 /app/ssl
RUN chmod +x /app/entrypoint.sh
EXPOSE 8081
ENV ASPNETCORE_URLS=http://+:8081
EXPOSE 4430
ENV ASPNETCORE_URLS=https://+:4430
ENTRYPOINT ["/app/entrypoint.sh"]

View File

@@ -1,5 +1,29 @@
#!/bin/sh
# Create SSL directory if it doesn't exist
mkdir -p /app/ssl
# Generate self-signed SSL certificate if not exists
if [ ! -f /app/ssl/api.crt ] || [ ! -f /app/ssl/api.key ]; then
echo "Generating new SSL certificate..."
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /app/ssl/api.key \
-out /app/ssl/api.crt \
-subj "/C=US/ST=State/L=City/O=Organization/CN=localhost"
# Set proper permissions
chmod 644 /app/ssl/api.crt
chmod 600 /app/ssl/api.key
# Create PFX for ASP.NET Core
openssl pkcs12 -export -out /app/ssl/api.pfx \
-inkey /app/ssl/api.key \
-in /app/ssl/api.crt \
-password pass:YourSecurePassword
fi
export ASPNETCORE_Kestrel__Certificates__Default__Path=/app/ssl/api.pfx
export ASPNETCORE_Kestrel__Certificates__Default__Password=YourSecurePassword
# Start the application
echo "Starting application..."
dotnet /app/AliasVault.Api.dll
dotnet AliasVault.Api.dll

View File

@@ -9,7 +9,7 @@ ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
WORKDIR /src
# Install Python which is required by the WebAssembly tools
RUN apt-get update && apt-get install -y python3 && apt-get clean
RUN apt-get update && apt-get install -y python3 openssl && apt-get clean
# Install the WebAssembly tools
RUN dotnet workload install wasm-tools
@@ -31,11 +31,19 @@ RUN dotnet publish "AliasVault.Client.csproj" -c "$BUILD_CONFIGURATION" -o /app/
# Final stage
FROM nginx:1.24.0 AS final
# Install OpenSSL for certificate generation
RUN apt-get update && apt-get install -y openssl && apt-get clean
WORKDIR /usr/share/nginx/html
COPY --from=publish /app/publish/wwwroot .
COPY /src/AliasVault.Client/nginx.conf /etc/nginx/nginx.conf
COPY /src/AliasVault.Client/entrypoint.sh /app/
# Create SSL directory
RUN mkdir -p /etc/nginx/ssl && chmod 755 /etc/nginx/ssl
RUN chmod +x /app/entrypoint.sh
EXPOSE 8080
ENV ASPNETCORE_URLS=http://+:8080
EXPOSE 80 443
ENV ASPNETCORE_URLS=http://+:80;https://+:443
ENTRYPOINT ["/app/entrypoint.sh"]

View File

@@ -1,6 +1,6 @@
#!/bin/sh
# Set the default API URL for localhost debugging
DEFAULT_API_URL="http://localhost:81"
DEFAULT_API_URL="https://localhost:4430"
DEFAULT_PRIVATE_EMAIL_DOMAINS="localmail.tld"
DEFAULT_SUPPORT_EMAIL=""
@@ -9,11 +9,24 @@ API_URL=${API_URL:-$DEFAULT_API_URL}
PRIVATE_EMAIL_DOMAINS=${PRIVATE_EMAIL_DOMAINS:-$DEFAULT_PRIVATE_EMAIL_DOMAINS}
SUPPORT_EMAIL=${SUPPORT_EMAIL:-$DEFAULT_SUPPORT_EMAIL}
# Create SSL directory if it doesn't exist
mkdir -p /etc/nginx/ssl
# Generate self-signed SSL certificate if not exists
if [ ! -f /etc/nginx/ssl/nginx.crt ] || [ ! -f /etc/nginx/ssl/nginx.key ]; then
echo "Generating new SSL certificate..."
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /etc/nginx/ssl/nginx.key \
-out /etc/nginx/ssl/nginx.crt \
-subj "/C=US/ST=State/L=City/O=Organization/CN=localhost"
# Set proper permissions
chmod 644 /etc/nginx/ssl/nginx.crt
chmod 600 /etc/nginx/ssl/nginx.key
fi
# Replace the default URL with the actual API URL
sed -i "s|http://localhost:5092|${API_URL}|g" /usr/share/nginx/html/appsettings.json
# Replace the default SMTP allowed domains with the actual allowed SMTP domains
# Note: this is used so the client knows which email addresses should be registered with the AliasVault server
# in order to be able to receive emails.
# Convert comma-separated list to JSON array
json_array=$(echo $PRIVATE_EMAIL_DOMAINS | awk '{split($0,a,","); printf "["; for(i=1;i<=length(a);i++) {printf "\"%s\"", a[i]; if(i<length(a)) printf ","} printf "]"}')

View File

@@ -15,9 +15,22 @@ http {
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
# HTTP server to redirect to HTTPS
server {
listen 8080;
listen 80;
server_name localhost;
return 301 https://$host$request_uri;
}
# HTTPS server
server {
listen 443 ssl;
server_name localhost;
ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
root /usr/share/nginx/html;