Merge pull request #1185 from aliasvault/1181-optimize-all-in-one-docker-container-config-and-add-documentation

Optimize all in one docker container config and add documentation
This commit is contained in:
Leendert de Borst
2025-09-15 18:50:40 +02:00
committed by GitHub
64 changed files with 2242 additions and 558 deletions

View File

@@ -26,6 +26,9 @@ HTTPS_PORT=443
SMTP_PORT=25
SMTP_TLS_PORT=587
# Whether to force redirect all HTTP traffic (80) to HTTPS (443). Defaults to true.
FORCE_HTTPS_REDIRECT=true
# ===========================================
# EMAIL SERVER CONFIGURATION
# ===========================================

View File

@@ -109,8 +109,8 @@ jobs:
echo "🔧 Testing admin password reset flow..."
# Run the reset password script with auto-confirm
echo "Running reset-admin-password.sh script..."
password_output=$(docker exec aliasvault-test reset-admin-password.sh -y 2>&1)
echo "Running reset-admin-password command..."
password_output=$(docker exec aliasvault-test aliasvault reset-admin-password -y 2>&1)
echo "Script output:"
echo "$password_output"

1
.gitignore vendored
View File

@@ -404,6 +404,7 @@ certificates/**/*.crt
certificates/**/*.key
certificates/**/*.pfx
certificates/**/*.pem
certificates/**/.hostname_marker
certificates/letsencrypt/**
# Secrets

2
.vscode/tasks.json vendored
View File

@@ -199,7 +199,7 @@
{
"label": "Build and watch Docs",
"type": "shell",
"command": "docker compose up",
"command": "docker compose build && docker compose up",
"problemMatcher": [],
"group": {
"kind": "build",

View File

@@ -65,33 +65,31 @@ AliasVault is available on:
[<img width="700" alt="Screenshot of AliasVault" src="docs/assets/img/screenshot.png">](https://app.aliasvault.net)
## Self-hosting
For full control over your own data you can self-host and install AliasVault on your own servers.
> [!NOTE]
> **Requirements:** 1 vCPU, 1GB RAM, 16GB disk, Docker ≥ 20.10, 64-bit Linux
### Install using install script
AliasVault can be self-hosted on your own servers using two different installation methods. Both use Docker, but they differ in how much is automated versus how much you manage yourself.
This method uses pre-built Docker images and works on minimal hardware specifications:
- **Option 1: Install Script** - Managed solution with automatic SSL (recommended for VPS/cloud)
- 64-bit Linux VM (Ubuntu/AlmaLinux) or Raspberry Pi, with root access
- Minimum: 1 vCPU, 1GB RAM, 16GB disk
- Docker ≥ 20.10 and Docker Compose ≥ 2.0
- **Option 2: Docker Compose** - Single container with manual setup for use with existing SSL infrastructure (NAS, homelab)
### Quick Start (Install Script)
```bash
# Download install script from latest stable release
# Download and run install script
curl -L -o install.sh https://github.com/aliasvault/aliasvault/releases/latest/download/install.sh
# Make install script executable and run it. This will create the .env file, pull the Docker images, and start the AliasVault containers.
chmod +x install.sh
./install.sh install
```
The install script will output the URL where the app is available. By default this is:
- Client: https://localhost
- Admin portal: https://localhost/admin
For other installation methods and more detailed steps, please read the [full installation guide](https://docs.aliasvault.net/installation) in the official docs.
> Note: If you want to change the default AliasVault ports you can do so in the `.env` file.
## Technical documentation
## Documentation
For more information about the installation process, manual setup instructions and other topics, please see the official documentation website:
- [Documentation website (docs.aliasvault.net) 📚](https://docs.aliasvault.net)
## Security Architecture
@@ -135,7 +133,7 @@ Core features that are being worked on:
👉 [View the full AliasVault roadmap here](https://github.com/aliasvault/aliasvault/issues/731)
### Got feedback or ideas?
Feel free to open an issue or join our [Discord](https://discord.gg/DsaXMTEtpF)! Contributions are warmly welcomed—whether in feature development, testing, or spreading the word. Get in touch on Discord if you're interested in contributing.
Feel free to open an issue or discussion on GitHub. We warmly welcome all contributions: whether its translating, testing, helping to build features, sharing feedback - or helping spread the word about AliasVault. Every bit of support helps the project grow, so dont hesitate to jump in and [say hi to us on Discord](https://discord.gg/DsaXMTEtpF)!
### Support the mission
AliasVault is open-source and community-driven. If you like what were building, consider supporting us through [Open Collective](https://opencollective.com/aliasvault) or through:

View File

@@ -1,13 +0,0 @@
<SonarLint>
<Rules>
<Rule>
<Key>S1135</Key>
<Parameters>
<Parameter>
<Name>sonarlint.rule.enabled</Name>
<Value>false</Value>
</Parameter>
</Parameters>
</Rule>
</Rules>
</SonarLint>

View File

@@ -1,4 +1,5 @@
@page "/user/login"
@using AliasVault.RazorComponents.Alerts
@using AliasVault.Shared.Models.Enums
<LayoutPageTitle>Log in</LayoutPageTitle>
@@ -11,29 +12,29 @@
@if (!IsAdminConfigured)
{
<div class="mt-8 p-6 bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 rounded-lg">
<div class="flex items-start">
<div class="flex-shrink-0">
<svg class="w-5 h-5 text-yellow-600 dark:text-yellow-400" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clip-rule="evenodd" />
</svg>
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-yellow-800 dark:text-yellow-200">
Admin User Not Configured
</h3>
<div class="mt-2 text-sm text-yellow-700 dark:text-yellow-300">
<p class="mb-3">The admin user has not been configured yet. To set up admin access:</p>
<ol class="list-decimal list-inside space-y-1 mb-3">
<li>Connect to your Docker container: <code class="bg-yellow-100 dark:bg-yellow-800 px-1 py-0.5 rounded text-xs">docker exec -it [container-name] /bin/bash</code></li>
<li>Run the password reset script: <code class="bg-yellow-100 dark:bg-yellow-800 px-1 py-0.5 rounded text-xs">reset-admin-password.sh</code></li>
<li>Restart the container to apply changes: <code class="bg-yellow-100 dark:bg-yellow-800 px-1 py-0.5 rounded text-xs">docker restart [container-name]</code></li>
</ol>
<p class="text-xs">Replace <code class="bg-yellow-100 dark:bg-yellow-800 px-1 py-0.5 rounded">[container-name]</code> with your actual container name, e.g. "aliasvault".</p>
<MessageInfo Title="Admin User Not Configured">
The admin user has not been configured yet. To set up admin access:
<ol class="list-decimal list-inside space-y-1 mb-3">
<li>
Connect to your Docker container:
<div>
<code class="bg-gray-700 text-white px-1 py-0.5 rounded text-xs">$ docker compose exec -it aliasvault /bin/bash</code>
</div>
</div>
</div>
</div>
</li>
<li>
Run the password reset script:
<div>
<code class="bg-gray-700 text-white px-1 py-0.5 rounded text-xs">$ aliasvault reset-admin-password</code>
</div>
</li>
<li>
Exit out of the container, then restart the container to apply changes:
<div>
<code class="bg-gray-700 text-white px-1 py-0.5 rounded text-xs">$ docker compose restart</code>
</div>
</li>
</ol>
</MessageInfo>
}
else
{

View File

@@ -48,7 +48,7 @@ public static class StartupTasks
if (string.IsNullOrEmpty(config.AdminPasswordHash))
{
Console.WriteLine("Admin password hash not configured - skipping admin user creation.");
Console.WriteLine("Run 'reset-admin-password.sh' to configure the admin password.");
Console.WriteLine("Run '$ aliasvault reset-admin-password' to configure the admin password.");
return;
}

View File

@@ -1270,11 +1270,6 @@ video {
border-color: rgb(239 68 68 / var(--tw-border-opacity));
}
.border-yellow-200 {
--tw-border-opacity: 1;
border-color: rgb(254 240 138 / var(--tw-border-opacity));
}
.border-yellow-500 {
--tw-border-opacity: 1;
border-color: rgb(234 179 8 / var(--tw-border-opacity));
@@ -1370,6 +1365,11 @@ video {
background-color: rgb(21 128 61 / var(--tw-bg-opacity));
}
.bg-orange-100 {
--tw-bg-opacity: 1;
background-color: rgb(255 237 213 / var(--tw-bg-opacity));
}
.bg-orange-400 {
--tw-bg-opacity: 1;
background-color: rgb(251 146 60 / var(--tw-bg-opacity));
@@ -1454,6 +1454,10 @@ video {
--tw-bg-opacity: 0.5;
}
.fill-current {
fill: currentColor;
}
.fill-primary-600 {
fill: #d68338;
}
@@ -1774,11 +1778,21 @@ video {
color: rgb(22 101 52 / var(--tw-text-opacity));
}
.text-orange-500 {
--tw-text-opacity: 1;
color: rgb(249 115 22 / var(--tw-text-opacity));
}
.text-orange-600 {
--tw-text-opacity: 1;
color: rgb(234 88 12 / var(--tw-text-opacity));
}
.text-orange-700 {
--tw-text-opacity: 1;
color: rgb(194 65 12 / var(--tw-text-opacity));
}
.text-primary-600 {
--tw-text-opacity: 1;
color: rgb(214 131 56 / var(--tw-text-opacity));
@@ -1814,11 +1828,6 @@ video {
color: rgb(255 255 255 / var(--tw-text-opacity));
}
.text-yellow-600 {
--tw-text-opacity: 1;
color: rgb(202 138 4 / var(--tw-text-opacity));
}
.text-yellow-700 {
--tw-text-opacity: 1;
color: rgb(161 98 7 / var(--tw-text-opacity));
@@ -2150,11 +2159,6 @@ video {
border-color: rgb(234 179 8 / var(--tw-border-opacity));
}
.dark\:border-yellow-800:is(.dark *) {
--tw-border-opacity: 1;
border-color: rgb(133 77 14 / var(--tw-border-opacity));
}
.dark\:bg-blue-800:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(30 64 175 / var(--tw-bg-opacity));
@@ -2251,10 +2255,6 @@ video {
background-color: rgb(113 63 18 / var(--tw-bg-opacity));
}
.dark\:bg-yellow-900\/20:is(.dark *) {
background-color: rgb(113 63 18 / 0.2);
}
.dark\:bg-opacity-80:is(.dark *) {
--tw-bg-opacity: 0.8;
}
@@ -2359,16 +2359,6 @@ video {
color: rgb(254 240 138 / var(--tw-text-opacity));
}
.dark\:text-yellow-300:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(253 224 71 / var(--tw-text-opacity));
}
.dark\:text-yellow-400:is(.dark *) {
--tw-text-opacity: 1;
color: rgb(250 204 21 / var(--tw-text-opacity));
}
.dark\:placeholder-gray-400:is(.dark *)::-moz-placeholder {
--tw-placeholder-opacity: 1;
color: rgb(156 163 175 / var(--tw-placeholder-opacity));

View File

@@ -30,6 +30,12 @@
<p class="text-lg text-gray-600 dark:text-gray-300 mb-8">
@Localizer["TaglineText"]
</p>
@if (_isHttpWarning)
{
<MessageInfo Title="@Localizer["HttpsWarningTitle"]">
@Localizer["HttpsWarningMessage"]
</MessageInfo>
}
<div class="space-y-4">
@if (Config.PublicRegistrationEnabled)
{
@@ -50,6 +56,7 @@
@code {
private IStringLocalizer Localizer => LocalizerFactory.Create("Pages.Auth.Start", "AliasVault.Client");
private bool _isHttpWarning = false;
/// <inheritdoc />
protected override async Task OnInitializedAsync()
@@ -62,5 +69,20 @@
// Already authenticated, redirect to home page.
NavigationManager.NavigateTo("/");
}
CheckHttpProtocol();
}
/// <summary>
/// Checks if the current URL is using HTTP and shows warning if needed.
/// Only shows warning for non-localhost hostnames since browsers allow crypto operations on localhost via HTTP.
/// </summary>
private void CheckHttpProtocol()
{
var uri = new Uri(NavigationManager.Uri);
var isLocalhost = uri.Host.Equals("localhost", StringComparison.OrdinalIgnoreCase) ||
uri.Host.Equals("127.0.0.1", StringComparison.OrdinalIgnoreCase) ||
uri.Host.Equals("::1", StringComparison.OrdinalIgnoreCase);
_isHttpWarning = uri.Scheme == "http" && !isLocalhost;
}
}

View File

@@ -8,7 +8,7 @@
<div class="container mx-auto px-4 py-4">
<div class="flex flex-col lg:flex-row justify-between items-center">
<p class="text-sm text-center text-gray-500 mb-4 lg:mb-0">
© 2024 <span>@AppInfo.ApplicationName v@(AppInfo.GetFullVersion())</span>. @Localizer["CopyrightText"]
© @(DateTime.Now.Year) <span>@AppInfo.ApplicationName v@(AppInfo.GetFullVersion())</span>. @Localizer["CopyrightText"]
</p>
<div class="hidden lg:block text-center text-gray-400 text-sm">@_randomQuote</div>
</div>

View File

@@ -74,4 +74,12 @@
<value>Log in with existing account</value>
<comment>Button text for logging in with existing account</comment>
</data>
<data name="HttpsWarningTitle" xml:space="preserve">
<value>HTTPS Required</value>
<comment>Title for HTTPS warning banner</comment>
</data>
<data name="HttpsWarningMessage" xml:space="preserve">
<value>Browsers only allow secure crypto operations via HTTPS, except for localhost. Login/registration won't work over HTTP with the current hostname. Please switch to HTTPS.</value>
<comment>Message explaining why HTTPS is required</comment>
</data>
</root>

View File

@@ -1525,6 +1525,11 @@ video {
border-color: rgb(254 215 170 / var(--tw-border-opacity));
}
.border-orange-500 {
--tw-border-opacity: 1;
border-color: rgb(249 115 22 / var(--tw-border-opacity));
}
.border-primary-100 {
--tw-border-opacity: 1;
border-color: rgb(253 222 133 / var(--tw-border-opacity));
@@ -1665,6 +1670,11 @@ video {
background-color: rgb(238 242 255 / var(--tw-bg-opacity));
}
.bg-orange-100 {
--tw-bg-opacity: 1;
background-color: rgb(255 237 213 / var(--tw-bg-opacity));
}
.bg-orange-50 {
--tw-bg-opacity: 1;
background-color: rgb(255 247 237 / var(--tw-bg-opacity));
@@ -1771,6 +1781,10 @@ video {
--tw-gradient-to: #d68338 var(--tw-gradient-to-position);
}
.fill-current {
fill: currentColor;
}
.fill-primary-600 {
fill: #d68338;
}
@@ -2146,6 +2160,16 @@ video {
color: rgb(67 56 202 / var(--tw-text-opacity));
}
.text-orange-500 {
--tw-text-opacity: 1;
color: rgb(249 115 22 / var(--tw-text-opacity));
}
.text-orange-700 {
--tw-text-opacity: 1;
color: rgb(194 65 12 / var(--tw-text-opacity));
}
.text-orange-800 {
--tw-text-opacity: 1;
color: rgb(154 52 18 / var(--tw-text-opacity));
@@ -3443,6 +3467,10 @@ video {
}
@media (min-width: 1024px) {
.lg\:fixed {
position: fixed;
}
.lg\:relative {
position: relative;
}
@@ -3503,6 +3531,10 @@ video {
display: none;
}
.lg\:min-h-screen {
min-height: 100vh;
}
.lg\:w-1\/2 {
width: 50%;
}

View File

@@ -1,9 +1,34 @@
/**
* Custom error class for crypto availability issues
*/
class CryptoNotAvailableError extends Error {
constructor(message) {
super(message);
this.name = 'CryptoNotAvailableError';
// Prevent stack trace from being captured
this.stack = '';
}
}
/**
* Check if crypto API is available and throw user-friendly error if not.
*/
function checkCryptoAvailable() {
if (!window.crypto || !window.crypto.subtle) {
const error = new CryptoNotAvailableError("Cryptographic operations are not available. Please ensure you are accessing AliasVault over HTTPS, as this is required for security features to work properly.");
console.error(error.message);
throw error;
}
}
/**
* AES (symmetric) encryption and decryption functions.
* @type {{encrypt: (function(*, *): Promise<string>), decrypt: (function(*, *): Promise<string>), decryptBytes: (function(*, *): Promise<Uint8Array>)}}
*/
window.cryptoInterop = {
encrypt: async function (plaintext, base64Key) {
checkCryptoAvailable();
const key = await window.crypto.subtle.importKey(
"raw",
Uint8Array.from(atob(base64Key), c => c.charCodeAt(0)),
@@ -36,6 +61,8 @@ window.cryptoInterop = {
);
},
decrypt: async function (base64Ciphertext, base64Key) {
checkCryptoAvailable();
const key = await window.crypto.subtle.importKey(
"raw",
Uint8Array.from(atob(base64Key), c => c.charCodeAt(0)),
@@ -61,6 +88,8 @@ window.cryptoInterop = {
return decoder.decode(decrypted);
},
decryptBytes: async function (base64Ciphertext, base64Key) {
checkCryptoAvailable();
const key = await window.crypto.subtle.importKey(
"raw",
Uint8Array.from(atob(base64Key), c => c.charCodeAt(0)),
@@ -96,6 +125,8 @@ window.rsaInterop = {
* @returns {Promise<{publicKey: string, privateKey: string}>} A promise that resolves to an object containing the public and private keys as JWK strings.
*/
generateRsaKeyPair : async function() {
checkCryptoAvailable();
const keyPair = await window.crypto.subtle.generateKey(
{
name: "RSA-OAEP",
@@ -122,6 +153,8 @@ window.rsaInterop = {
* @returns {Promise<string>} A promise that resolves to the encrypted data as a base64-encoded string.
*/
encryptWithPublicKey : async function(plaintext, publicKey) {
checkCryptoAvailable();
const publicKeyObj = await window.crypto.subtle.importKey(
"jwk",
JSON.parse(publicKey),
@@ -151,6 +184,8 @@ window.rsaInterop = {
* @returns {Promise<Uint8Array>} A promise that resolves to the decrypted data as a Uint8Array.
*/
decryptWithPrivateKey: async function(ciphertext, privateKey) {
checkCryptoAvailable();
try {
// Parse the private key
let parsedPrivateKey = JSON.parse(privateKey);

View File

@@ -10,8 +10,8 @@ LABEL org.opencontainers.image.description="Nginx reverse proxy for AliasVault.
# Install OpenSSL and inotify-tools for certificate watching
RUN apk add --no-cache openssl inotify-tools
# Copy configuration and entrypoint script
COPY apps/server/nginx.conf /etc/nginx/nginx.conf
# Copy all nginx configurations and entrypoint script
COPY apps/server/nginx*.conf /etc/nginx/
COPY apps/server/status.html /usr/share/nginx/html/status.html
COPY apps/server/entrypoint.sh /docker-entrypoint.sh

View File

@@ -0,0 +1,35 @@
@inherits ComponentBase
@if (ChildContent != null)
{
<div class="bg-orange-100 border-l-4 border-orange-500 text-orange-700 p-4 mb-6" role="alert">
<div class="flex">
<div class="py-1">
<svg class="fill-current h-6 w-6 text-orange-500 mr-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path d="M2.93 17.07A10 10 0 1 1 17.07 2.93 10 10 0 0 1 2.93 17.07zm12.73-1.41A8 8 0 1 0 4.34 4.34a8 8 0 0 0 11.32 11.32zM9 11V9h2v6H9v-4zm0-6h2v2H9V5z"/>
</svg>
</div>
<div>
@if (!string.IsNullOrEmpty(Title))
{
<p class="font-bold">@Title</p>
}
<div class="text-sm">@ChildContent</div>
</div>
</div>
</div>
}
@code {
/// <summary>
/// Gets or sets the title to display.
/// </summary>
[Parameter]
public string? Title { get; set; }
/// <summary>
/// Gets or sets the child content to display.
/// </summary>
[Parameter]
public RenderFragment? ChildContent { get; set; }
}

View File

@@ -3,17 +3,67 @@
# 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/cert.pem ] || [ ! -f /etc/nginx/ssl/key.pem ]; then
# Select the appropriate nginx configuration based on FORCE_HTTPS_REDIRECT
# Default to true (nginx-443.conf) for backward compatibility
# Only disable redirect if explicitly set to "false"
if [ "${FORCE_HTTPS_REDIRECT:-true}" = "false" ]; then
echo "Using nginx-80-443.conf (HTTP and HTTPS without redirect)"
cp /etc/nginx/nginx-80-443.conf /etc/nginx/nginx.conf
else
echo "Using nginx-443.conf (HTTP to HTTPS redirect enabled - default)"
cp /etc/nginx/nginx-443.conf /etc/nginx/nginx.conf
fi
# Function to check if certificate needs regeneration
needs_cert_regeneration() {
# If cert doesn't exist, need to generate
if [ ! -f /etc/nginx/ssl/cert.pem ] || [ ! -f /etc/nginx/ssl/key.pem ]; then
return 0
fi
# Check if we have a hostname marker file
if [ -f /etc/nginx/ssl/.hostname_marker ]; then
STORED_HOSTNAME=$(cat /etc/nginx/ssl/.hostname_marker)
if [ "$STORED_HOSTNAME" != "${HOSTNAME:-localhost}" ]; then
echo "Hostname changed from '$STORED_HOSTNAME' to '${HOSTNAME:-localhost}', regenerating certificate..."
return 0
fi
else
# No marker file, regenerate to be safe
return 0
fi
return 1
}
# Generate self-signed SSL certificate if not exists or hostname changed
if needs_cert_regeneration; then
echo "Generating new SSL certificate (10 years validity)..."
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
-keyout /etc/nginx/ssl/key.pem \
-out /etc/nginx/ssl/cert.pem \
-subj "/C=US/ST=State/L=City/O=Organization/CN=localhost"
HOSTNAME_VALUE="${HOSTNAME:-localhost}"
if [ "$HOSTNAME_VALUE" = "localhost" ] || [ -z "$HOSTNAME_VALUE" ]; then
# Default localhost-only configuration
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
-keyout /etc/nginx/ssl/key.pem \
-out /etc/nginx/ssl/cert.pem \
-subj "/C=US/ST=State/L=City/O=Organization/CN=localhost"
else
# Generate certificate with the hostname and include localhost as SAN
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
-keyout /etc/nginx/ssl/key.pem \
-out /etc/nginx/ssl/cert.pem \
-subj "/C=US/ST=State/L=City/O=AliasVault/CN=${HOSTNAME_VALUE}" \
-addext "subjectAltName=DNS:${HOSTNAME_VALUE},DNS:localhost,IP:127.0.0.1"
fi
# Set proper permissions
chmod 644 /etc/nginx/ssl/cert.pem
chmod 600 /etc/nginx/ssl/key.pem
# Store current hostname for change detection
echo "${HOSTNAME:-localhost}" > /etc/nginx/ssl/.hostname_marker
chmod 644 /etc/nginx/ssl/.hostname_marker
fi
# Create the appropriate SSL configuration based on LETSENCRYPT_ENABLED

143
apps/server/nginx-443.conf Normal file
View File

@@ -0,0 +1,143 @@
# This is the Nginx configuration file for the AliasVault reverse-proxy container.
# which exposes all AliasVault services via 443 (HTTPS) with a self-signed or Let's Encrypt certificate.
# It also redirects all non-ACME challenge requests from HTTP to HTTPS.
events {
worker_connections 1024;
}
http {
client_max_body_size 25M;
upstream client {
server client:3000 max_fails=1 fail_timeout=5s;
}
upstream api {
server api:3001 max_fails=1 fail_timeout=5s;
}
upstream admin {
server admin:3002 max_fails=1 fail_timeout=5s;
}
# Preserve any existing X-Forwarded-* headers, this is relevant if AliasVault
# is running behind another reverse proxy.
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 172.16.0.0/12;
set_real_ip_from 192.168.0.0/16;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Enable gzip compression, which reduces the amount of data that needs to be transferred
# to speed up WASM load times.
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
server {
listen 80;
server_name _;
# Handle ACME challenge for Let's Encrypt certificate validation
location /.well-known/acme-challenge/ {
allow all;
root /var/www/certbot;
try_files $uri =404;
default_type "text/plain";
add_header Cache-Control "no-cache";
break;
}
# Redirect all other HTTP traffic to HTTPS
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name _;
# Include the appropriate SSL certificate configuration generated
# by the entrypoint script.
include /etc/nginx/ssl.conf;
# Security headers
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Cross-Origin-Resource-Policy "same-origin" always;
add_header Content-Security-Policy "frame-ancestors 'self'" always;
# Root for static files
root /usr/share/nginx/html;
# Error page handler location (internal use only)
location = /status.html {
internal;
try_files /status.html =404;
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
add_header Expires "0";
}
# Admin interface
location /admin {
proxy_pass http://admin;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Prefix /admin/;
# Rewrite HTTP redirects to HTTPS
proxy_redirect http:// https://;
# Add WebSocket support for Blazor server
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
# Show status page if admin is down
proxy_intercept_errors on;
error_page 502 503 504 =503 /status.html;
}
# API endpoints
location /api {
proxy_pass http://api;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Show status page if api is down
proxy_intercept_errors on;
error_page 502 503 504 =503 /status.html;
}
# Client app (root path)
location / {
proxy_pass http://client;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Rewrite HTTP redirects to HTTPS
proxy_redirect http:// https://;
# Show status page if client is down
proxy_intercept_errors on;
error_page 502 503 504 =503 /status.html;
}
}
}

View File

@@ -0,0 +1,128 @@
# This is the main Nginx configuration file for the AliasVault reverse-proxy container.
# which exposes all AliasVault services via both 80 (HTTP)
# and 443 (HTTPS) with either a self-signed or Let's Encrypt certificate.
events {
worker_connections 1024;
}
http {
client_max_body_size 25M;
upstream client {
server client:3000 max_fails=1 fail_timeout=5s;
}
upstream api {
server api:3001 max_fails=1 fail_timeout=5s;
}
upstream admin {
server admin:3002 max_fails=1 fail_timeout=5s;
}
# Preserve any existing X-Forwarded-* headers, this is relevant if AliasVault
# is running behind another reverse proxy.
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 172.16.0.0/12;
set_real_ip_from 192.168.0.0/16;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Enable gzip compression, which reduces the amount of data that needs to be transferred
# to speed up WASM load times.
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
server {
listen 80;
listen 443 ssl;
server_name _;
# Include the appropriate SSL certificate configuration generated
# by the entrypoint script (only applies to 443).
include /etc/nginx/ssl.conf;
# Security headers
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Cross-Origin-Resource-Policy "same-origin" always;
add_header Content-Security-Policy "frame-ancestors 'self'" always;
# Root for static files
root /usr/share/nginx/html;
# Handle ACME challenge for Let's Encrypt certificate validation
location /.well-known/acme-challenge/ {
allow all;
root /var/www/certbot;
try_files $uri =404;
default_type "text/plain";
add_header Cache-Control "no-cache";
break;
}
# Error page handler location (internal use only)
location = /status.html {
internal;
try_files /status.html =404;
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
add_header Expires "0";
}
# Admin interface
location /admin {
proxy_pass http://admin;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Prefix /admin/;
# Add WebSocket support for Blazor server
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
# Show status page if admin is down
proxy_intercept_errors on;
error_page 502 503 504 =503 /status.html;
}
# API endpoints
location /api {
proxy_pass http://api;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Show status page if api is down
proxy_intercept_errors on;
error_page 502 503 504 =503 /status.html;
}
# Client app (root path)
location / {
proxy_pass http://client;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Show status page if client is down
proxy_intercept_errors on;
error_page 502 503 504 =503 /status.html;
}
}
}

View File

@@ -18,24 +18,39 @@ COPY shared/ ./shared/
# Install required .NET workloads and restore packages once for the entire solution
WORKDIR /src/apps/server
# Install workloads and restore packages once for the entire solution
RUN dotnet workload install wasm-tools && \
dotnet restore aliasvault.sln
# Build all applications
# Build each application in separate layers to avoid lock contention
# Build API
RUN dotnet publish AliasVault.Api/AliasVault.Api.csproj \
-c Release -o /app/api --no-restore && \
dotnet publish AliasVault.Client/AliasVault.Client.csproj \
-c Release -o /app/client --no-restore && \
dotnet publish AliasVault.Admin/AliasVault.Admin.csproj \
-c Release -o /app/admin --no-restore && \
dotnet publish Services/AliasVault.SmtpService/AliasVault.SmtpService.csproj \
-c Release -o /app/smtp --no-restore && \
dotnet publish Services/AliasVault.TaskRunner/AliasVault.TaskRunner.csproj \
-c Release -o /app/taskrunner --no-restore && \
dotnet publish Utilities/AliasVault.InstallCli/AliasVault.InstallCli.csproj \
-c Release -o /app/installcli --no-restore && \
# Clean up .NET debug files and unnecessary files
find /app -name "*.pdb" -delete && \
-c Release -o /app/api --no-restore
# Build Client (contains WASM which can be slow)
RUN dotnet publish AliasVault.Client/AliasVault.Client.csproj \
-c Release -o /app/client --no-restore
# Build Admin
RUN dotnet publish AliasVault.Admin/AliasVault.Admin.csproj \
-c Release -o /app/admin --no-restore
# Build SMTP Service
RUN dotnet publish Services/AliasVault.SmtpService/AliasVault.SmtpService.csproj \
-c Release -o /app/smtp --no-restore
# Build Task Runner
RUN dotnet publish Services/AliasVault.TaskRunner/AliasVault.TaskRunner.csproj \
-c Release -o /app/taskrunner --no-restore
# Build Install CLI
RUN dotnet publish Utilities/AliasVault.InstallCli/AliasVault.InstallCli.csproj \
-c Release -o /app/installcli --no-restore
# Clean up .NET debug files and unnecessary files
RUN find /app -name "*.pdb" -delete && \
find /app -name "*.xml" -not -name "*.deps.json" -delete && \
find /app -name "*.Development.json" -delete && \
find /app -name "web.config" -delete
@@ -109,31 +124,33 @@ RUN apt-get update && \
/app/taskrunner \
/app/installcli \
/database \
/certificates/ssl \
/logs/postgres \
/etc/nginx/ssl \
/var/run/postgresql \
/var/www/certbot \
/etc/s6-overlay/s6-rc.d/user/contents.d
# Copy built applications and all configuration files from builder stage
COPY --from=dotnet-builder /app /app
# Copy configuration files and scripts directly to their destinations
COPY dockerfiles/all-in-one/reset-admin-password.sh /usr/local/bin/reset-admin-password.sh
# Copy all scripts from scripts directory to /usr/local/bin
COPY dockerfiles/all-in-one/scripts/ /usr/local/bin/
COPY apps/server/AliasVault.Client/nginx.conf /app/client/nginx.conf
COPY apps/server/nginx.conf /etc/nginx/nginx.conf
COPY dockerfiles/all-in-one/config/nginx-80-443.conf /etc/nginx/nginx-80-443.conf
COPY dockerfiles/all-in-one/config/nginx-443.conf /etc/nginx/nginx-443.conf
COPY apps/server/status.html /usr/share/nginx/html/status.html
COPY dockerfiles/all-in-one/s6-scripts /etc/s6-overlay/s6-rc.d/
# Copy InstallCLI to /usr/local/bin and configure everything
RUN cp -r /app/installcli /usr/local/bin/aliasvault-cli && \
chmod +x /usr/local/bin/aliasvault-cli/AliasVault.InstallCli \
/usr/local/bin/reset-admin-password.sh && \
chmod +x /usr/local/bin/aliasvault-cli/AliasVault.InstallCli && \
ln -s /usr/local/bin/aliasvault-cli/AliasVault.InstallCli /usr/local/bin/aliasvault-cli.sh && \
sed -i 's/server client:3000/server localhost:3000/g; \
s/server api:3001/server localhost:3001/g; \
s/server admin:3002/server localhost:3002/g' /etc/nginx/nginx.conf && \
# Make all scripts executable and create symlinks without .sh extension
for script in /usr/local/bin/*.sh; do \
if [ -f "$script" ]; then \
chmod +x "$script" && \
basename="$(basename "$script" .sh)" && \
ln -sf "$script" "/usr/local/bin/$basename"; \
fi; \
done && \
find /etc/s6-overlay/s6-rc.d -type f \( -name "run" -o -name "up" -o -name "script" \) -exec chmod +x {} \; && \
cd /etc/s6-overlay/s6-rc.d/user/contents.d && \
touch init postgres api client admin smtp taskrunner nginx notification && \
@@ -146,15 +163,17 @@ ENV ALIASVAULT_VERBOSITY=0 \
IP_LOGGING_ENABLED=true \
SUPPORT_EMAIL="" \
PRIVATE_EMAIL_DOMAINS="" \
HOSTNAME=localhost \
POSTGRES_HOST=localhost \
POSTGRES_PORT=5432 \
POSTGRES_USER=aliasvault \
POSTGRES_DATABASE=aliasvault \
FORCE_HTTPS_REDIRECT=false \
S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0 \
S6_VERBOSITY=0
EXPOSE 80 443 25 587
VOLUME ["/database", "/certificates", "/logs", "/secrets"]
VOLUME ["/database", "/logs", "/secrets"]
HEALTHCHECK --interval=30s --timeout=10s --start-period=90s --retries=3 \
CMD curl -f -k https://localhost/api || exit 1
CMD curl -f http://localhost/api || exit 1
ENTRYPOINT ["/init"]

View File

@@ -18,9 +18,7 @@ docker build -f dockerfiles/all-in-one/Dockerfile -t aliasvault-allinone:local .
docker run -d \
--name aliasvault \
-p 80:80 \
-p 443:443 \
-v ./database:/database \
-v ./certificates:/certificates \
-v ./logs:/logs \
-v ./secrets:/secrets \
aliasvault-allinone:local

View File

@@ -0,0 +1,126 @@
# Nginx configuration for AliasVault all-in-one container with forced HTTP to HTTPS redirect
# and uses a self-signed cert.
events {
worker_connections 1024;
}
http {
client_max_body_size 25M;
upstream client {
server localhost:3000 max_fails=1 fail_timeout=5s;
}
upstream api {
server localhost:3001 max_fails=1 fail_timeout=5s;
}
upstream admin {
server localhost:3002 max_fails=1 fail_timeout=5s;
}
# Preserve any existing X-Forwarded-* headers, this is relevant if AliasVault
# is running behind another reverse proxy.
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 172.16.0.0/12;
set_real_ip_from 192.168.0.0/16;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Enable gzip compression, which reduces the amount of data that needs to be transferred
# to speed up WASM load times.
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
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 - redirects all traffic to HTTPS
server {
listen 80;
server_name _;
# Redirect all HTTP traffic to HTTPS
return 301 https://$host$request_uri;
}
# HTTPS server
server {
listen 443 ssl;
server_name _;
# Include the appropriate SSL certificate configuration generated
# by the entrypoint script.
include /etc/nginx/ssl.conf;
# Security headers
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Cross-Origin-Resource-Policy "same-origin" always;
add_header Content-Security-Policy "frame-ancestors 'self'" always;
# Root for static files
root /usr/share/nginx/html;
# Error page handler location (internal use only)
location = /status.html {
internal;
try_files /status.html =404;
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
add_header Expires "0";
}
# Admin interface
location /admin {
proxy_pass http://admin;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Prefix /admin/;
# Add WebSocket support for Blazor server
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
# Show status page if admin is down
proxy_intercept_errors on;
error_page 502 503 504 =503 /status.html;
}
# API endpoints
location /api {
proxy_pass http://api;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Show status page if api is down
proxy_intercept_errors on;
error_page 502 503 504 =503 /status.html;
}
# Client app (root path)
location / {
proxy_pass http://client;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Show status page if client is down
proxy_intercept_errors on;
error_page 502 503 504 =503 /status.html;
}
}
}

View File

@@ -0,0 +1,188 @@
# This is the main Nginx configuration file for the AliasVault all-in-one container.
# which exposes all AliasVault services via both 80 (HTTP)
# and optionally 443 (HTTPS) with self-signed cert.
events {
worker_connections 1024;
}
http {
client_max_body_size 25M;
upstream client {
server localhost:3000 max_fails=1 fail_timeout=5s;
}
upstream api {
server localhost:3001 max_fails=1 fail_timeout=5s;
}
upstream admin {
server localhost:3002 max_fails=1 fail_timeout=5s;
}
# Preserve any existing X-Forwarded-* headers, this is relevant if AliasVault
# is running behind another reverse proxy.
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 172.16.0.0/12;
set_real_ip_from 192.168.0.0/16;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Enable gzip compression, which reduces the amount of data that needs to be transferred
# to speed up WASM load times.
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
server {
listen 80;
server_name _;
# Security headers
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Cross-Origin-Resource-Policy "same-origin" always;
add_header Content-Security-Policy "frame-ancestors 'self'" always;
# Root for static files
root /usr/share/nginx/html;
# Error page handler location (internal use only)
location = /status.html {
internal;
try_files /status.html =404;
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
add_header Expires "0";
}
# Admin interface
location /admin {
proxy_pass http://admin;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Prefix /admin/;
# Add WebSocket support for Blazor server
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
# Show status page if admin is down
proxy_intercept_errors on;
error_page 502 503 504 =503 /status.html;
}
# API endpoints
location /api {
proxy_pass http://api;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Show status page if api is down
proxy_intercept_errors on;
error_page 502 503 504 =503 /status.html;
}
# Client app (root path)
location / {
proxy_pass http://client;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Show status page if client is down
proxy_intercept_errors on;
error_page 502 503 504 =503 /status.html;
}
}
# HTTPS server
server {
listen 443 ssl;
server_name _;
# Include the appropriate SSL certificate configuration generated
# by the entrypoint script.
include /etc/nginx/ssl.conf;
# Security headers
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Cross-Origin-Resource-Policy "same-origin" always;
add_header Content-Security-Policy "frame-ancestors 'self'" always;
# Root for static files
root /usr/share/nginx/html;
# Error page handler location (internal use only)
location = /status.html {
internal;
try_files /status.html =404;
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
add_header Expires "0";
}
# Admin interface
location /admin {
proxy_pass http://admin;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Prefix /admin/;
# Add WebSocket support for Blazor server
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
# Show status page if admin is down
proxy_intercept_errors on;
error_page 502 503 504 =503 /status.html;
}
# API endpoints
location /api {
proxy_pass http://api;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Show status page if api is down
proxy_intercept_errors on;
error_page 502 503 504 =503 /status.html;
}
# Client app (root path)
location / {
proxy_pass http://client;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Show status page if client is down
proxy_intercept_errors on;
error_page 502 503 504 =503 /status.html;
}
}
}

View File

@@ -1,4 +1,4 @@
#!/bin/sh -e
#!/command/with-contenv sh
# AliasVault Container Initialization Script
# This script runs once at container startup and handles all initialization tasks
@@ -154,37 +154,81 @@ else
chmod 700 /database/postgres
fi
# Future: Database migrations could go here
# log 1 "[init] Checking for database migrations..."
# if [ -f /app/migrations/pending ]; then
# log 1 "[init] → Running database migrations..."
# # Run migration logic here
# fi
# Function to check if certificate needs regeneration
needs_cert_regeneration() {
# If cert doesn't exist, need to generate
if [ ! -f /certificates/ssl/cert.pem ] || [ ! -f /certificates/ssl/key.pem ]; then
return 0
fi
# Generate SSL certificates if needed
if [ ! -f /certificates/ssl/cert.pem ] || [ ! -f /certificates/ssl/key.pem ]; then
# Check if we have a hostname marker file
if [ -f /certificates/ssl/.hostname_marker ]; then
STORED_HOSTNAME=$(cat /certificates/ssl/.hostname_marker)
if [ "$STORED_HOSTNAME" != "${HOSTNAME:-localhost}" ]; then
log 0 "[init] Hostname changed from '$STORED_HOSTNAME' to '${HOSTNAME:-localhost}', regenerating certificate..."
return 0
fi
else
# No marker file, regenerate to be safe
return 0
fi
return 1
}
# Generate SSL certificates if needed or hostname changed
if needs_cert_regeneration; then
log 0 ""
log 0 "[init] Generating SSL certificates..."
mkdir -p /certificates/ssl
if [ "$VERBOSITY" -ge 2 ]; then
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
-keyout /certificates/ssl/key.pem \
-out /certificates/ssl/cert.pem \
-subj "/C=US/ST=State/L=City/O=AliasVault/CN=${HOSTNAME:-localhost}"
HOSTNAME_VALUE="${HOSTNAME:-localhost}"
if [ "$HOSTNAME_VALUE" = "localhost" ] || [ -z "$HOSTNAME_VALUE" ]; then
# Default localhost-only configuration
if [ "$VERBOSITY" -ge 2 ]; then
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
-keyout /certificates/ssl/key.pem \
-out /certificates/ssl/cert.pem \
-subj "/C=US/ST=State/L=City/O=AliasVault/CN=localhost"
else
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
-keyout /certificates/ssl/key.pem \
-out /certificates/ssl/cert.pem \
-subj "/C=US/ST=State/L=City/O=AliasVault/CN=localhost" \
>/dev/null 2>&1
fi
else
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
-keyout /certificates/ssl/key.pem \
-out /certificates/ssl/cert.pem \
-subj "/C=US/ST=State/L=City/O=AliasVault/CN=${HOSTNAME:-localhost}" \
>/dev/null 2>&1
# Generate certificate with the hostname and include localhost as SAN
if [ "$VERBOSITY" -ge 2 ]; then
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
-keyout /certificates/ssl/key.pem \
-out /certificates/ssl/cert.pem \
-subj "/C=US/ST=State/L=City/O=AliasVault/CN=${HOSTNAME_VALUE}" \
-addext "subjectAltName=DNS:${HOSTNAME_VALUE},DNS:localhost,IP:127.0.0.1"
else
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
-keyout /certificates/ssl/key.pem \
-out /certificates/ssl/cert.pem \
-subj "/C=US/ST=State/L=City/O=AliasVault/CN=${HOSTNAME_VALUE}" \
-addext "subjectAltName=DNS:${HOSTNAME_VALUE},DNS:localhost,IP:127.0.0.1" \
>/dev/null 2>&1
fi
fi
chmod 600 /certificates/ssl/key.pem
chmod 644 /certificates/ssl/cert.pem
# Store current hostname for change detection
echo "${HOSTNAME:-localhost}" > /certificates/ssl/.hostname_marker
chmod 644 /certificates/ssl/.hostname_marker
log 0 "[init] Self-signed SSL certificates generated"
else
log 0 "[init] ✅ Self-signed SSL certificates already exist"
fi
echo ""
echo "[init] Waiting for all services to be ready... this can take a short while..."
echo ""

View File

@@ -19,6 +19,16 @@ ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDS
ssl_prefer_server_ciphers off;
SSLEOF
# Configure nginx based on FORCE_HTTPS_REDIRECT environment variable
FORCE_HTTPS_REDIRECT=${FORCE_HTTPS_REDIRECT:-false}
if [[ "${FORCE_HTTPS_REDIRECT}" == "true" ]]; then
echo "Configuring nginx with HTTPS-only (443) - redirects HTTP to HTTPS"
cp /etc/nginx/nginx-443.conf /etc/nginx/nginx.conf
else
echo "Configuring nginx with HTTP and HTTPS support (80+443)"
cp /etc/nginx/nginx-80-443.conf /etc/nginx/nginx.conf
fi
echo "Starting Nginx reverse proxy..."
# Set nginx error log level based on verbosity

View File

@@ -37,16 +37,16 @@ if [ "$VERBOSITY" -le 1 ]; then
# Admin password hash exists - show the legacy warning
echo "🔑 Admin Login:"
echo " • Username: admin"
echo " • Password: (previously set - to reset the admin password, login to this container via \`docker exec -it [container-name] /bin/bash\` and run: reset-admin-password.sh)"
echo " • Password: (previously set - to reset the admin password, login to this container via \`docker exec -it aliasvault /bin/bash\` and run: aliasvault reset-admin-password)"
echo ""
else
# No admin password hash file - show setup instructions
echo "🔑 Admin Setup:"
echo " • Admin user is not configured by default"
echo " • To configure admin access:"
echo " 1. docker exec -it [container-name] /bin/bash"
echo " 2. reset-admin-password.sh"
echo " 3. Restart the container"
echo " 1. $ docker exec -it aliasvault /bin/bash"
echo " 2. $ aliasvault reset-admin-password"
echo " 3. $ docker compose restart"
echo ""
fi

View File

@@ -0,0 +1,35 @@
#!/bin/bash
# Simple AliasVault command dispatcher wrapper which allows
# running AliasVault commands from the Docker container CLI
# like `aliasvault reset-admin-password`.
case "$1" in
reset-admin-password)
shift
exec /usr/local/bin/reset-admin-password.sh "$@"
;;
hash-password)
shift
exec /usr/local/bin/aliasvault-cli/AliasVault.InstallCli hash-password "$@"
;;
help|--help|-h|"")
echo "AliasVault Commands"
echo ""
echo "Usage: aliasvault <command> [options]"
echo ""
echo "Commands:"
echo " reset-admin-password Reset admin password"
echo " hash-password Hash a password"
echo " help Show this help"
echo ""
echo "Examples:"
echo " aliasvault reset-admin-password -y"
echo " aliasvault hash-password 'mypassword'"
;;
*)
echo "Unknown command: $1"
echo "Run 'aliasvault help' for usage"
exit 1
;;
esac

View File

@@ -0,0 +1,36 @@
# Docker Compose file for the AliasVault all-in-one container
#
# Specific for NAS devices:
# - Uses custom HTTP ports by default to avoid conflicts
# - Uses named bind mounts for the database, logs and secrets to ensure they are persisted
#
version: "3"
services:
aliasvault:
image: ghcr.io/aliasvault/aliasvault:latest
container_name: aliasvault
restart: unless-stopped
ports:
- "1080:80"
- "1443:443"
- "25:25"
- "587:587"
volumes:
- avdata:/database
- avlogs:/logs
- avsecrets:/secrets
environment:
HOSTNAME: "localhost"
PUBLIC_REGISTRATION_ENABLED: "true"
IP_LOGGING_ENABLED: "true"
FORCE_HTTPS_REDIRECT: "false"
SUPPORT_EMAIL: ""
PRIVATE_EMAIL_DOMAINS: ""
volumes:
avdata:
avlogs:
avsecrets:

View File

@@ -1,5 +1,8 @@
version: "3"
# Docker Compose file for the AliasVault all-in-one container
#
# This is the general purpose template which uses local folder bind mounts for the database, logs and secrets.
# - For NAS devices, its safer to use the docker-compose.all-in-one.nas.yml template instead.
#
services:
aliasvault:
image: ghcr.io/aliasvault/aliasvault:latest
@@ -14,12 +17,13 @@ services:
volumes:
- ./database:/database
- ./certificates:/certificates
- ./logs:/logs
- ./secrets:/secrets
environment:
HOSTNAME: "localhost"
PUBLIC_REGISTRATION_ENABLED: "true"
IP_LOGGING_ENABLED: "true"
FORCE_HTTPS_REDIRECT: "false"
SUPPORT_EMAIL: ""
PRIVATE_EMAIL_DOMAINS: ""

68
docs/404.html Normal file
View File

@@ -0,0 +1,68 @@
---
layout: default
title: 404 - Page not found
permalink: /404.html
nav_exclude: true
search_exclude: true
---
<style>
.error-404 {
text-align: center;
padding: 4rem 2rem;
}
.error-404 h1 {
font-size: 6rem;
color: #f49541;
margin-bottom: 1rem;
}
.error-404 h2 {
font-size: 2rem;
margin-bottom: 1rem;
color: #f8f9fa;
}
.error-404 p {
font-size: 1.2rem;
margin-bottom: 2rem;
color: #d1d5db;
}
.error-404 .btn {
display: inline-block;
padding: 0.75rem 1.5rem;
background-color: #d68338;
color: white;
text-decoration: none;
border-radius: 4px;
transition: background-color 0.2s;
}
.error-404 .btn:hover {
background-color: #f49541;
}
.error-404 .links {
margin-top: 2rem;
}
.error-404 .links a {
margin: 0 1rem;
color: #f49541;
text-decoration: underline;
}
.error-404 .links a:hover {
color: #ffd5a8;
}
</style>
<div class="error-404">
<h1>404</h1>
<h2>Page Not Found</h2>
<p>The page you're looking for doesn't exist or may have been moved.</p>
<p>This could happen if the documentation structure has been reorganized or the page has been renamed.</p>
<a href="{{ '/' | relative_url }}" class="btn">Go to Home</a>
<div class="links">
<p>Or try these helpful links:</p>
<a href="{{ '/installation/' | relative_url }}">Installation Guide</a>
<a href="{{ '/browser-extension/' | relative_url }}">Browser Extension</a>
<a href="{{ '/mobile-app/' | relative_url }}">Mobile App</a>
</div>
</div>

View File

@@ -6,3 +6,7 @@ gem "just-the-docs"
# If you want to use GitHub Pages, remove the "gem "jekyll"" above and
# uncomment the line below. To upgrade, run `bundle update github-pages`.
gem "github-pages", group: :jekyll_plugins
group :jekyll_plugins do
gem "jekyll-sitemap"
end

View File

@@ -284,6 +284,7 @@ PLATFORMS
DEPENDENCIES
github-pages
jekyll-sitemap
just-the-docs
BUNDLED WITH

View File

@@ -38,3 +38,19 @@ callouts:
note:
title: Note
color: purple
important:
title: Important
color: yellow
# 404 page
defaults:
- scope:
path: "404.html"
values:
sitemap: false
# Sitemap settings
url: "https://docs.aliasvault.net"
plugins:
- jekyll-sitemap
- jekyll-redirect-from

View File

@@ -0,0 +1,44 @@
require 'webrick'
module Jekyll
class FourOhFourPage < StaticFile
def write(dest)
true
end
end
class FourOhFourGenerator < Generator
priority :low
def generate(site)
site.static_files << FourOhFourPage.new(site, site.dest, '/', '404.html')
end
end
end
# Override WEBrick to serve 404.html for missing files
if defined?(WEBrick)
module WEBrick
class HTTPServlet::FileHandler
alias_method :do_GET_original, :do_GET
def do_GET(req, res)
do_GET_original(req, res)
rescue HTTPStatus::NotFound => ex
return_404_page(req, res)
rescue => ex
raise ex
end
def return_404_page(req, res)
path = File.join(@config[:DocumentRoot], '404.html')
if File.exist?(path)
res.body = File.read(path)
res['content-type'] = 'text/html'
else
raise HTTPStatus::NotFound
end
end
end
end
end

View File

@@ -38,5 +38,11 @@ $purple-100: #ffd5a8;
$purple-200: #f49541;
$purple-300: #d68338;
// Orange Colors
$orange-000: #f8b963;
$orange-100: #ffd5a8;
$orange-200: #f49541;
$orange-300: #d68338;
// Navigation additional
$nav-button-color: #f49541;

View File

@@ -9,11 +9,11 @@ permalink: /
# AliasVault Documentation
{: .fs-9 }
A self-hostable, end-to-end encrypted password manager with a built-in alias generator and email server.
A privacy-first password manager with built-in email aliasing. Fully encrypted and self-hostable.
{: .fs-6 .fw-300 }
[Server Installation](./installation/install){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 }
[Self-host Install](./installation){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 }
[View on GitHub](https://github.com/aliasvault/aliasvault){: .btn .fs-5 .mb-4 .mb-md-0 }
---
@@ -37,7 +37,7 @@ All data is end-to-end encrypted on the client. Your master password never leave
Generate virtual email addresses for each identity. Emails sent to these addresses are instantly visible in the AliasVault app.
### Virtual Identities
Create separate identities for different purposes, each with its own email aliases and credentials.
Create separate identities for different purposes, each with its own email aliases.
---

View File

@@ -1,22 +0,0 @@
---
layout: default
title: Database Backup
parent: Advanced
nav_order: 4
---
# Database Backup
In order to backup the database, you can use the `install.sh` script. This script will stop all services, export the database to a file, and then restart the services.
```bash
./install.sh db-backup > backup.sql.gz
```
# Database Restore
To restore the database, you can use the `install.sh` script. This script will stop all services, drop the database, import the database from a file, and then restart the services.
```bash
./install.sh db-restore < backup.sql.gz
```

View File

@@ -1,14 +0,0 @@
---
layout: default
title: Advanced
parent: Server Installation
nav_order: 2
---
# Advanced Installation
The following guides provide more advanced installation options for AliasVault. These options are not required for the basic installation, but may be useful for advanced users.
- [Manual Setup](manual-setup.md) - Step-by-step manual installation without the install script
- [Reverse Proxy Configuration](reverse-proxy-configuration.md) - Configure AliasVault with your existing reverse proxy
- [Build from Source](build-from-source.md) - Build AliasVault from source code
- [Database Configuration](database.md) - Advanced database configuration options

View File

@@ -1,139 +0,0 @@
---
layout: default
title: Manual Setup
parent: Advanced
nav_order: 1
---
# Manual Setup
If you prefer to manually set up AliasVault instead of using the `install.sh` script, this README provides step-by-step instructions.
**Prerequisities:**
- Docker (20.10+) and Docker Compose (2.0+) installed on your system
- See instructions: [https://docs.docker.com/engine/install/](https://docs.docker.com/engine/install/)
- Knowledge of working with direct Docker commands
- Knowledge of .env files
- OpenSSL for generating random passwords
---
{: .toc }
* TOC
{:toc}
---
## Steps
Follow these steps to manually install AliasVault on your own server.
1. **Clone the git repository**
```bash
# Clone repository
git clone https://github.com/aliasvault/aliasvault.git
# Navigate to the AliasVault directory
cd aliasvault
```
2. **Create required directories**
Create the following directories in your project root:
```bash
# Create required directories
mkdir -p certificates/ssl database/postgres
```
3. **Create .env file**
```bash
# Copy the .env.example file to create a new .env file
cp .env.example .env
```
4. **Set all required settings in .env**
Open the .env file in your favorite text editor and fill in all required variables
by following the instructions inside the file.
```bash
# Open the .env file with your favorite editor, e.g. nano.
nano .env
```
5. **Start the docker containers**
After you are done configuring your .env file, you can start the Docker Compose stack:
```bash
# Start the docker compose stack
docker compose up -d
```
6. **Access AliasVault**
AliasVault should now be running. You can access it at:
- Admin Panel: https://localhost/admin
- Username: admin
- Password: [Use the password you set in the .env file]
- Client Website: https://localhost/
- Create your own account from here
> Note: if you changed the default ports from 80/443 to something else in the .env file, use those ports to access AliasVault here.
7. **Configuring private email domains**
By default, the AliasVault private email domains feature is disabled. If you wish to enable this to use your own private domains to create email aliases with, please read the `Email Server Setup` section in the main installation guide [Basic Install](../install.md#3-email-server-setup).
For more information, read the article explaining the differences between AliasVault's [private and public domains](../../misc/private-vs-public-email.md).
## Important Notes
- Make sure to save both the admin password and PostgreSQL password in a secure location.
- Always keep your .env file secure and do not share it, as it contains sensitive information.
- The PostgreSQL data is persisted in the `database/postgres` directory.
- The docker-compose.yml file uses the `:latest` tag for containers by default. This means it always uses the latest available AliasVault version. In order to update AliasVault to a newer version at a later time, you can pull new containers when they are available with this command:
```
docker compose pull && docker compose down && docker compose up -d
```
## Using a Custom Reverse Proxy (e.g. Cloudflare Tunnel)
AliasVault includes its own internal reverse proxy (nginx) container that routes traffic to other containers. By default, the built-in nginx container (`reverse-proxy`) makes AliasVault's services available at:
- **Client**: `http://localhost/`
- **API**: `http://localhost/api`
- **Admin**: `http://localhost/admin`
If you want to use your own reverse proxy setup (e.g. with a Cloudflare Tunnel), you **must** ensure the following:
- Your custom proxy/tunnel **points to the AliasVault `reverse-proxy` container**, **not** directly to the client, API, or admin containers.
- The forwarding protocol must be **HTTPS**, since the `reverse-proxy` container listens on port `443` for secure connections.
> ⚠️ Failing to route through the reverse-proxy container correctly will break the app. Errors such as HTTP 502 often indicate a misconfigured reverse proxy.
If you're using **Cloudflare Tunnel**, you will likely encounter TLS verification issues. In that case, go to the Cloudflare dashboard and enable the **"No TLS Verify"** option for your tunnel configuration. This tells Cloudflare to skip certificate validation when connecting to the internal reverse-proxy over HTTPS.
## Troubleshooting
If you encounter any miscellaneous issues during the setup:
1. Check the Docker logs:
```bash
docker compose logs
```
2. Ensure all required ports (80, 443, 25, 587 and 5432) are available and not being used by other services.
3. Verify that all variables in the .env file are set correctly.
4. Check PostgreSQL container logs specifically:
```bash
docker compose logs postgres
```
For more detailed troubleshooting information, please refer to the full [troubleshooting guide](../troubleshooting.md).
## FAQ
### Why does AliasVault use its own reverse proxy?
AliasVault requires precise routing between its client, API, and admin interfaces. These are structured under `/`, `/api`, and `/admin`. A unified nginx reverse proxy ensures that all AliasVault's containers are accessible under the same hostname and path structure. If you use your own reverse proxy, you must replicate this logic exactly. See the [nginx.conf](https://raw.githubusercontent.com/aliasvault/aliasvault/refs/heads/main/apps/server/nginx.conf) configuration that's used by the official container for reference.

View File

@@ -1,141 +0,0 @@
---
layout: default
title: Reverse Proxy Configuration
parent: Advanced
nav_order: 2
---
# Reverse Proxy Configuration
This guide is intended for users who already have a self-hosted reverse proxy setup (such as nginx, Apache, or Cloudflare Tunnel) and want to expose AliasVault through it. In this case, the recommended approach is to forward a single hostname (e.g., `aliasvault.example.com`) to the internal reverse proxy container that AliasVault provides.
If you do **not** already have an existing reverse proxy, you can simply rely on the built-in reverse proxy that comes with AliasVault, as it's fully capable of handling all routing, SSL termination, and WebSocket support out of the box.
## Overview
AliasVault includes its own internal reverse proxy (nginx) that handles routing between its three core services:
- **Client Application** (`/`) The main user interface
- **API Server** (`/api`) REST API endpoints
- **Admin Panel** (`/admin`) Administrative interface
When using an external reverse proxy, you **must** forward requests to the `reverse-proxy` container. Do **not** route traffic directly to the individual services.
## Why AliasVault Uses Its Own Reverse Proxy
AliasVaults internal reverse proxy ensures proper routing and configuration of all services under one domain:
1. **Unified Hostname** All services operate under the same domain (e.g., `aliasvault.example.com`)
2. **Path-Based Routing** Correct dispatch of `/`, `/api`, and `/admin` requests
3. **Security Headers** Consistent headers across services
4. **SSL Termination** Central SSL/TLS handling
5. **WebSocket Support** Required for the Blazor-based admin interface
## Internal Nginx Configuration Structure
AliasVault's reverse proxy follows a path-based routing configuration like this:
```nginx
# Upstream services
upstream client {
server client:3000;
}
upstream api {
server api:3001;
}
upstream admin {
server admin:3002;
}
server {
listen 443 ssl;
server_name _;
location /admin {
proxy_pass http://admin;
# WebSocket support and headers
}
location /api {
proxy_pass http://api;
}
location / {
proxy_pass http://client;
}
}
```
## Simplest Setup (Recommended)
Forward all traffic from your external reverse proxy to the AliasVault internal reverse proxy container. This avoids manual path-based routing.
### Example: External Nginx Reverse Proxy
```nginx
server {
listen 80;
server_name aliasvault.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name aliasvault.example.com;
ssl_certificate /path/to/your/certificate.crt;
ssl_certificate_key /path/to/your/private.key;
location / {
proxy_pass https://aliasvault-internal:443;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
## Port Configuration
AliasVaults internal reverse proxy defaults to port `443`. If this port is already in use, you can change it in the `.env` file inside your AliasVault folder:
```
HTTP_PORT=80
HTTPS_PORT=443
```
Make sure your external proxy points to the correct port.
## Common Issues and Solutions
### HTTP 502 Bad Gateway
**Cause**: External proxy routing to wrong container.
**Fix**: Ensure it routes to `reverse-proxy` container, not `client`, `api`, or `admin`.
### WebSocket Errors
**Cause**: WebSocket headers not forwarded.
**Fix**: Make sure `Upgrade` and `Connection` headers are preserved.
### SSL/TLS Verification (e.g., Cloudflare Tunnel)
**Cause**: TLS verification fails.
**Fix**: Enable “No TLS Verify” in your Cloudflare Tunnel configuration.
### Partial Routing Failures
**Cause**: External proxy modifies paths.
**Fix**: Do not strip or rewrite paths. Proxy should pass `/`, `/api`, `/admin` as-is.
## Testing
After setup, verify:
- `https://your-domain.com/` loads the client app
- `https://your-domain.com/api` returns OK
- `https://your-domain.com/admin` loads the admin interface
All services must be available under the **same** hostname.
## Security Considerations
- Always use HTTPS in production
- Preserve headers like `X-Real-IP`, `X-Forwarded-For`
- Consider adding rate limiting or IP restrictions on your external proxy
- Keep certificates and secrets secure
For advanced scenarios or troubleshooting, refer to the main [troubleshooting guide](../troubleshooting.md).

View File

@@ -0,0 +1,32 @@
---
layout: default
title: Database Operations
parent: Advanced
grand_parent: Docker Compose
nav_order: 4
---
# Database Operations
This page explains how to import/export on the AliasVault server database via Docker commands.
## Database Export
In order to backup the AliasVault server database (which includes all encrypted user vaults as well), you can use the following command. Run this command from the directory where your AliasVault `docker-compose.yml` is located.
```bash
$ docker compose exec aliasvault pg_dump -U aliasvault aliasvault > backup.sql
```
## Database Import
To restore a previously exported database, you can use the following snippet. Run these commands from the directory where your AliasVault `docker-compose.yml` is located.
```bash
# Drop database first (warning: this can't be undone!)
docker compose exec -T aliasvault psql -U postgres -d postgres -c "DROP DATABASE IF EXISTS aliasvault WITH (FORCE);"
# Create new empty database
docker compose exec -T aliasvault psql -U postgres -d postgres -c "CREATE DATABASE aliasvault OWNER aliasvault;"
# Import backup
docker compose exec -T aliasvault psql -U aliasvault aliasvault < backup.sql
```

View File

@@ -0,0 +1,9 @@
---
layout: default
title: Advanced
parent: Docker Compose
nav_order: 2
---
# Advanced Installation
The following guides provide more advanced installation options for AliasVault. These options are not required for the basic installation, but may be useful for advanced users.

View File

@@ -0,0 +1,30 @@
---
layout: default
title: Stop/start
parent: Advanced
grand_parent: Docker Compose
nav_order: 2
---
# Stopping and starting AliasVault
You can stop and start AliasVault via the default docker compose commands. Run these commands from the directory where your AliasVault `docker-compose.yml` is located.
## Stop
To stop AliasVault:
```bash
$ docker compose down
```
## Start
To start AliasVault:
```bash
$ docker compose up -d
```
## Restart
To restart AliasVault (note: when making changes to the `docker-compose.yml`, you'll need to manually stop and start to make the new changes be applied)
```bash
$ docker compose restart
```

View File

@@ -0,0 +1,20 @@
---
layout: default
title: Uninstall
parent: Advanced
grand_parent: Docker Compose
nav_order: 4
---
# Uninstall
To uninstall AliasVault, run the following command. This will stop and remove the AliasVault containers and remove the Docker images.
{: .note }
This will not delete any data stored in the database. If you wish to delete all data, you should manually delete the `database` directory and the other directories created by AliasVault.
### Steps
1. Run docker compose down and remove any local Docker images related to AliasVault.
```bash
$ docker compose down --rmi all
```

View File

@@ -0,0 +1,186 @@
---
layout: default
title: Docker Compose
parent: Self-host Install
redirect_from:
- /installation/advanced/manual-setup
- /installation/advanced/manual-setup.html
nav_order: 2
---
# Self-host using Docker Compose (single container)
The following guide will walk you through the steps to install AliasVault via the All-In-One Docker container. This container uses `s6-overlay` to combine all AliasVault's services into one image for convenience. The only downside compared to the `install.sh` installer is that this version does NOT come with SSL/TLS support, so you'll have to make the container available through your own SSL/TLS proxy.
{: .important-title }
> Requirements:
> - Docker (20.10+) and Docker Compose (2.0+) installed on your system
> - See instructions: [https://docs.docker.com/engine/install/](https://docs.docker.com/engine/install/)
> - You have existing SSL/TLS proxy infrastructure (Traefik, Nginx, HAProxy, Cloudflare Tunnel)
> - Knowledge of working with direct Docker commands
> - Knowledge of .yml and .env files
## 1. Basic installation
1. Create a new folder where you want to store AliasVault's data and configuration folders.
```bash
mkdir aliasvault
cd aliasvault
```
2. Create a new `docker-compose.yml` file with the following contents. Note: the directories specified in `volumes:` will be auto-created in the current folder on container first start.
```yaml
services:
aliasvault:
image: ghcr.io/aliasvault/aliasvault:latest
container_name: aliasvault
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "25:25"
- "587:587"
volumes:
- ./database:/database
- ./logs:/logs
- ./secrets:/secrets
environment:
HOSTNAME: "localhost"
PUBLIC_REGISTRATION_ENABLED: "true"
IP_LOGGING_ENABLED: "true"
FORCE_HTTPS_REDIRECT: "false"
SUPPORT_EMAIL: ""
PRIVATE_EMAIL_DOMAINS: ""
```
3. Run `docker-compose up -d` to start the container.
4. After the container has started, AliasVault should now be running. You can access it at:
- Admin Panel: http://localhost/admin
- **Username:** admin
- **Password:** [*Read instructions on page*]
- Client Website: http://localhost/
- Create your own account from here
- API: http://localhost/api
- Used for configuring the browser extension and mobile app to connect to your server
---
## 2. SSL/TLS configuration
To use AliasVault securely, HTTPS is required in the following situations:
- When accessing the web app from any address other than `localhost` (due to browser security restrictions)
- When using the mobile apps, which require the API URL to have a valid TLS certificate; otherwise, the app will not connect
You must set up and configure your own TLS/SSL infrastructure (such as Traefik, Nginx, HAProxy, or Cloudflare Tunnel) to make the AliasVault container accessible over HTTPS with a valid SSL/TLS certificate. For example: `https://aliasvault.yourdomain.com`.
---
## 3. Email Server Setup
AliasVault includes a built-in email server that allows you to generate email aliases on-the-fly for every website you use, and receive the emails straight in AliasVault.
{: .note }
If you skip this step, AliasVault will default to use public email domains offered by SpamOK. While this still works for creating aliases, it has privacy limitations. For complete privacy and control, we recommend setting up your own domain.
[Learn more about the differences between private and public email domains](../misc/private-vs-public-email.md).
---
### Requirements
- A **public IPv4 address** with ports 25 and 587 forwarded to your AliasVault server
- Open ports **25** and **587** on your server firewall for email SMTP traffic (*NOTE: some residential IP's block this, check with your ISP*).
#### Verifying Port Access
While the AliasVault docker containers are running, use `telnet` to confirm your public IP allows access to the ports:
```bash
# Test standard SMTP port
telnet <your-server-public-ip> 25
# Test secure SMTP port
telnet <your-server-public-ip> 587
```
### Choose your configuration: primary domain vs subdomain
AliasVault can be configured under:
- **A primary (top-level) domain**
Example: `your-aliasvault.net`. This allows you to receive email on `%alias%@your-aliasvault.net`.
- **A subdomain of your existing domain**
Example: `aliasvault.example.net`. This allows you to receive email on `%alias%@aliasvault.example.net`. Email sent to your main domain remains unaffected and will continue arriving in your usual inbox.
---
#### a) Setup using a primary domain
##### DNS Configuration
Configure the following DNS records **on your primary domain** (e.g. `your-aliasvault.net`):
| Name | Type | Priority | Content | TTL |
|------|------|----------|---------------------------|-----|
| mail | A | | `<your-server-public-ip>` | 3600 |
| @ | MX | 10 | `mail.your-aliasvault.net`| 3600 |
> Replace `<your-server-public-ip>` with your actual server IP.
##### Example
- `mail.your-aliasvault.net` points to your server IP.
- Email to `@your-aliasvault.net` will be handled by your AliasVault server.
---
#### b) Setup using a subdomain
##### DNS Configuration
Configure the following DNS records **on your subdomain setup** (for example, `aliasvault.example.com`):
| Name | Type | Priority | Content | TTL |
|---------------------------|------|----------|-------------------------------|-----|
| mail.aliasvault | A | | `<your-server-public-ip>` | 3600 |
| aliasvault | MX | 10 | `mail.aliasvault.example.com` | 3600 |
> 🔹 Explanation:
> - `mail.aliasvault` creates a DNS A record for `mail.aliasvault.example.com` pointing to your server IP.
> - The MX record on `aliasvault.example` tells senders to send their mail addressed to `%@aliasvault.example.com` to `mail.aliasvault.example.com`.
> Replace `<your-server-public-ip>` with your actual servers IP address.
##### Example
- `mail.aliasvault.example.com` points to your server IP.
- Emails to `user@aliasvault.example.com` will be handled by your AliasVault server.
This keeps the email configuration of your primary domain (`example.com`) completely separate, so you can keep receiving email on your normal email addresses and have unique AliasVault addresses too.
---
### Configuring AliasVault
After setting up your DNS, you have to configure AliasVault to let it know which email domains it should support. Update the `docker-compose.yml` file:
```bash
# ...
environment:
PRIVATE_EMAIL_DOMAINS: "yourdomain1.com,yourdomain2.com"
# ...
```
After updating the docker-compose.yml file, restart the Docker Compose stack:
```bash
# To apply new environment variables, containers must be recreated.
docker compose down
docker compose up -d
```
Afterwards, when you login to the AliasVault web app, you should now be able to create an alias with your configured private domain and be able to receive email on it.
{: .note }
Important: DNS propagation can take up to 24-48 hours. During this time, email delivery might be inconsistent.
If you encounter any issues, feel free to join the [Discord chat](https://discord.gg/DsaXMTEtpF) to get help from other users and maintainers.

View File

@@ -0,0 +1,82 @@
---
layout: default
title: Troubleshooting
parent: Docker Compose
nav_order: 3
---
# Troubleshooting
This guide covers common issues and troubleshooting steps for AliasVault encountered during installation, updates or general maintenance.
{: .toc }
* TOC
{:toc}
---
## Check Docker Container Status
For any issues you might encounter, the first step is to check the Docker containers health. This will give you a quick insight into the status of the individual containers which will help you identify the root cause of the issue.
1. Check the Docker container running status:
```bash
$ docker compose ps
```
2. Check the Docker container logs
```bash
$ docker compose logs
```
3. Try restarting the Docker container
```bash
$ docker compose restart
```
---
## Check AliasVault Text Logs
All AliasVault services log information and errors to text files. These files are located in the `logs` directory. You can check the logs of a specific service by running the following command:
```bash
$ cat logs/[service-name].txt
```
---
## Common Issues
Below are some common issues you might encounter and how to troubleshoot them.
### 1. No emails being received
If you are not receiving emails on your aliases, check the following:
- Verify DNS records are correctly configured
- Ensure ports 25 and 587 are accessible
- Check your server's firewall settings
- Verify that your ISP/hosting provider allows SMTP traffic and does not block port 25
Refer to the [installation guide](./#3-email-server-setup) for more information on how to configure your DNS records and ports.
### 2. Forgot AliasVault Admin Password
If you have lost your admin password, you can reset it by running the `aliasvault reset-admin-password` option. This will generate a new random password and update the secret. After that it will restart the AliasVault containers to apply the changes.
1. SSH into the aliasvault container:
```bash
$ docker compose exec -it aliasvault /bin/bash
```
2. Run the reset-admin-password.sh script:
```bash
$ aliasvault reset-admin-password
```
3. Remember the password outputted by the step above. Then quit out of the SSH session (ctrl+C) and then restart the container:
```bash
$ docker compose restart
```
4. You can now login to the admin panel (/admin) with the new password.
---
## Other Issues
If you encounter any other issues not mentioned here and need help, please join our Discord server or create an issue on the GitHub repository and we will be happy to help you out.
Find all contact information on the contact page of our website: [https://www.aliasvault.net/contact](https://www.aliasvault.net/contact)

View File

@@ -0,0 +1,66 @@
---
layout: default
title: Update
parent: Docker Compose
nav_order: 1
---
# Updating AliasVault
{: .no_toc }
<details open markdown="block">
<summary>
Table of contents
</summary>
{: .text-delta }
1. TOC
{:toc}
</details>
## Before You Begin
You can see the latest available version of AliasVault on [GitHub](https://github.com/aliasvault/aliasvault/releases).
{: .warning }
Before updating, it's recommended to backup your database and other important data. You can do this by making
a copy of the `database` and `certificates` directories.
## Standard Update Process
For most version updates, you can use the standard update process. The container will automatically handle database migrations on startup:
1. Navigate to your AliasVault directory:
```bash
cd /path/to/your/aliasvault
```
2. Pull the latest Docker image:
```bash
docker compose pull
```
3. Restart the container with the new image:
```bash
docker compose down && docker compose up -d
```
## Version-Specific Upgrade Guides
While database migrations are automated, some releases may require manual file/config migration steps. Always check this page before updating to ensure you don't miss any required manual steps.
> Currently there are no version-specific manual migration steps required for the single container setup. Check back here when updating to ensure you haven't missed any new requirements.
## Additional Update Options
### Installing a Specific Version
If you need to install a specific version instead of the latest, you can do the following. Note: downgrading to a previous version is not officially supported and may lead to unexpected issues, as database schema changes may prevent older versions from working correctly.
1. Edit your `docker-compose.yml` file
2. Change the image tag from `:latest` to a specific version:
```yaml
# ...
image: ghcr.io/aliasvault/aliasvault:0.23.0 # Replace with desired version
# ... rest of configuration
```
3. Pull and restart:
```bash
docker compose pull
docker compose down && docker compose up -d
```

View File

@@ -1,8 +1,121 @@
---
layout: default
title: Server Installation
title: Self-host Install
nav_order: 2
---
# Server Installation
The following guide will walk you through the steps to install AliasVault on your own server. Minimum experience with Docker and Linux is required.
# Self-host Install
AliasVault can be self-hosted on your own servers using two different installation methods. Both use Docker, but they differ in how much is automated versus how much you manage yourself.
## Which Installation Method to Choose?
### 🚀 **Option 1: Install Script**
The installer script is a **fully managed solution** that handles everything for you. Simply run it on a clean VM/LXC with Docker installed, and it will set up all required containers, configure SSL certificates and provide CLI helpers for easy updates and maintenance.
### 🛠️ **Option 2: Docker Compose**
If you prefer manual setup and **have existing SSL infrastructure**, use the all-in-one Docker image via Docker Compose. It works with your existing SSL proxy (Traefik, HAProxy, Caddy, etc.) and gives you full control over the configuration. Note: because this install method does not include a CLI, future updates may require some manual migrations.
| | **Option 1: Install Script (multi-container)** | **Option 2: Docker Compose (single container)** |
|--------------------------|---------------------------------------------------|-----------------------------------------------|
| **Best for** | ☁️ VPS/VM/Proxmox, cloud hosts, DigitalOcean, AWS/Azure | 🏠 NAS/Synology/Unraid, Raspberry Pi, home servers |
| **Internet accessible** | Direct internet access with ports 80/443 | Behind existing infrastructure |
| **TLS/SSL** | Built-in reverse proxy + Let's Encrypt (automatic) | Bring your own (Traefik, Nginx, HAProxy, Caddy) |
| **Containers** | Multiple containers (client, api, postgres, task runner, smtp, admin, reverse proxy) | Single bundled container (all-in-one) |
| **Configuration** | Automatic docker-compose.yml setup | Standard Docker commands |
| **Updates** | `install.sh` assisted updates & migrations | `docker pull` (manual); occasional manual migrations |
| **Admin actions** | `install.sh` helpers for admin password reset | SSH into container for certain tasks (e.g. password reset) |
| **Setup style** | Managed, opinionated, production-ready defaults | Fits into existing homelab/stack tools (Portainer compatible) |
| **Build from source** | Supported | Pre-built container only |
| **Choose if…** | You want auto SSL and a managed stack | You already have TLS and prefer manual control |
| | [**Self-host via Install Script →**](./script){: .btn .btn-primary } | [**Self-host via Docker →**](./docker-compose){: .btn .btn-primary } |
### Quick Decision Guide
**Go with the Install Script if:**
- ✅ You have a fresh VM or VPS dedicated to AliasVault
- ✅ You want automatic SSL setup without hassle
- ✅ You prefer managed updates and maintenance
- ✅ You're new to Docker or want the simplest setup
**Go with Docker Compose if:**
- ✅ You're already running other Docker containers on this host
- ✅ You have existing SSL infrastructure (reverse proxy)
- ✅ You want to integrate with your homelab tools (Portainer, etc.)
- ✅ You prefer manual control over the configuration
---
## Frequently Asked Questions
<details style="margin-bottom: 10px;">
<summary style="background-color: #4a5568; color: #ffffff; padding: 10px; border-radius: 5px; cursor: pointer;">What's the difference between multi-container and single container?</summary>
<div style="background-color: #2d3748; color: #ffffff; padding: 15px; border-left: 3px solid #4299e1;" markdown="1">
| **Multi-container (Installer Script)** | **Single container (Manual Setup)** |
|----------------------------------------|-------------------------------------|
| Separates services into individual containers | All services bundled in one container |
| Easier to scale individual components | Simpler to manage with Docker commands |
| Uses docker-compose for orchestration | Lower resource overhead |
| Better for production deployments | Better for home labs and personal use |
</div>
</details>
<details style="margin-bottom: 10px;">
<summary style="background-color: #4a5568; color: #ffffff; padding: 10px; border-radius: 5px; cursor: pointer;">Do I need to handle SSL/TLS certificates myself?</summary>
<div style="background-color: #2d3748; color: #ffffff; padding: 15px; border-left: 3px solid #4299e1;" markdown="1">
- **Installer Script**: No, it includes automatic Let's Encrypt certificates
- **Manual Setup**: Yes, you need your own reverse proxy for HTTPS
</div>
</details>
<details style="margin-bottom: 10px;">
<summary style="background-color: #4a5568; color: #ffffff; padding: 10px; border-radius: 5px; cursor: pointer;">How do updates work?</summary>
<div style="background-color: #2d3748; color: #ffffff; padding: 15px; border-left: 3px solid #4299e1;" markdown="1">
| Method | Update Process |
|--------|---------------|
| **Installer Script** | Run `./install.sh update` for automated updates and migrations |
| **Manual Setup** | Use `docker pull` to get the latest image; manual migrations may be required |
</div>
</details>
<details style="margin-bottom: 10px;">
<summary style="background-color: #4a5568; color: #ffffff; padding: 10px; border-radius: 5px; cursor: pointer;">Can I migrate between installation methods?</summary>
<div style="background-color: #2d3748; color: #ffffff; padding: 15px; border-left: 3px solid #4299e1;" markdown="1">
Yes! Both methods use the same bind mount directories (`/database`, `/certificates`, `/logs`, `/secrets`), making migration straightforward. Simply stop/uninstall via one method and follow the installation steps for the other - your data will be preserved.
</div>
</details>
<details style="margin-bottom: 10px;">
<summary style="background-color: #4a5568; color: #ffffff; padding: 10px; border-radius: 5px; cursor: pointer;">What are the system requirements?</summary>
<div style="background-color: #2d3748; color: #ffffff; padding: 15px; border-left: 3px solid #4299e1;" markdown="1">
**Minimum requirements:**
- 64-bit Linux OS (Ubuntu or RHEL-based recommended)
- 1 vCPU, 1GB RAM, 16GB disk
- Docker CE (≥ 20.10) and Docker Compose (≥ 2.0)
**Network requirements:**
- Ports 80 and 443 available
- Optional: Ports 25 and 587 for private email domains
</div>
</details>
<details style="margin-bottom: 10px;">
<summary style="background-color: #4a5568; color: #ffffff; padding: 10px; border-radius: 5px; cursor: pointer;">Can I build from source?</summary>
<div style="background-color: #2d3748; color: #ffffff; padding: 15px; border-left: 3px solid #4299e1;" markdown="1">
- **Installer Script**: Yes, optional build from source is supported
- **Manual Setup**: No, uses pre-built container images only
</div>
</details>

View File

@@ -2,6 +2,7 @@
layout: default
title: Build from Source
parent: Advanced
grand_parent: Install Script
nav_order: 3
---
@@ -18,13 +19,13 @@ Building from source requires more resources:
## Steps
1. Clone the repository
```bash
git clone https://github.com/aliasvault/aliasvault.git
cd aliasvault
$ git clone https://github.com/aliasvault/aliasvault.git
$ cd aliasvault
```
2. Make the build script executable and run it. This will create the .env file, build the Docker images locally from source, and start the AliasVault containers. Follow the on-screen prompts to configure AliasVault.
```bash
chmod +x install.sh
./install.sh build
$ chmod +x install.sh
$ ./install.sh build
```
> **Note:** The complete build process can take a while depending on your hardware (5-15 minutes).

View File

@@ -0,0 +1,25 @@
---
layout: default
title: Database Operations
parent: Advanced
grand_parent: Install Script
nav_order: 4
---
# Database Operations
This page explains how to import/export on the AliasVault server database via the `./install.sh` script.
## Database Export
In order to backup the AliasVault server database (which includes all encrypted user vaults as well), you can use the `install.sh` script. This script will stop all services, export the database to a file, and then restart the services.
```bash
$ ./install.sh db-export > backup.sql.gz
```
## Database Import
To restore a previously exported database, you can use the `install.sh` script. This script will stop all services, drop the database, import the database from a file, and then restart the services.
```bash
$ ./install.sh db-import < backup.sql.gz
```

View File

@@ -0,0 +1,9 @@
---
layout: default
title: Advanced
parent: Install Script
nav_order: 4
---
# Advanced Installation
The following guides provide more advanced installation options for AliasVault. These options are not required for the basic installation, but may be useful for advanced users.

View File

@@ -1,30 +1,31 @@
---
layout: default
title: Start/stop
parent: Server Installation
title: Stop/start
parent: Advanced
grand_parent: Install Script
nav_order: 2
---
# Starting and stopping AliasVault
You can start and stop AliasVault easily by using the install script.
# Stopping and starting AliasVault
You can stop and start AliasVault easily by using the install script.
## Stop
To stop AliasVault, run the install script with the `stop` option. This will stop all running AliasVault containers.
```bash
./install.sh stop
$ ./install.sh stop
```
## Start
To start AliasVault, run the install script with the `start` option. This will start all AliasVault containers.
```bash
./install.sh start
$ ./install.sh start
```
## Restart
To restart AliasVault, run the install script with the `restart` option. This will restart all AliasVault containers.
```bash
./install.sh restart
$ ./install.sh restart
```

View File

@@ -1,13 +1,14 @@
---
layout: default
title: Uninstall
parent: Server Installation
parent: Advanced
grand_parent: Install Script
nav_order: 4
---
# Uninstall
To uninstall AliasVault, run the install script with the `uninstall` option. This will stop and remove the AliasVault containers, remove the Docker images, and delete the .env file.
To uninstall AliasVault, run the install script with the `uninstall` option. This will stop and remove the AliasVault containers and remove any local AliasVault Docker images.
{: .note }
This will not delete any data stored in the database. If you wish to delete all data, you should manually delete the `database` directory and the other directories created by AliasVault.
@@ -15,5 +16,5 @@ This will not delete any data stored in the database. If you wish to delete all
### Steps
1. Run the install script with the `uninstall` option
```bash
./install.sh uninstall
$ ./install.sh uninstall
```

View File

@@ -0,0 +1,73 @@
---
layout: default
title: Installer Script (multi-container)
parent: Self-host Installs
nav_order: 1
has_children: true
---
# Installer Script (multi-container)
The installer script provides a managed, production-ready deployment of AliasVault using multiple Docker containers. This method includes automatic SSL certificates, built-in reverse proxy, and CLI-based management tools.
{: .important }
> **Best for:** VPS, cloud hosting (AWS, Azure, DigitalOcean), dedicated servers with direct internet access
1. **New Installation?** Start with the [Installation Guide](./installation)
2. **Upgrading?** Check the [Update Guide](./update/)
3. **Need Help?** Visit [Troubleshooting](./troubleshooting) or join our [Discord](https://discord.gg/DsaXMTEtpF)
## 📚 Documentation
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; margin: 20px 0;">
<div style="background: #4a5568; border: 1px solid #d1d5da; border-radius: 8px; padding: 20px;">
<h3 style="margin-top: 0;">🚀 Getting Started</h3>
<p>Initial installation and configuration</p>
<ul style="list-style: none; padding: 0;">
<li>📖 <a href="./installation">Installation Guide</a></li>
<li>🔒 <a href="./installation#tls-ssl-configuration">SSL/TLS Setup</a></li>
<li>📧 <a href="./installation#email-server-setup">Email Configuration</a></li>
<li>👤 <a href="./installation#configure-account-registration">Registration Settings</a></li>
</ul>
</div>
<div style="background: #4a5568; border: 1px solid #d1d5da; border-radius: 8px; padding: 20px;">
<h3 style="margin-top: 0;">🔄 Updates & Maintenance</h3>
<p>Keep your instance up-to-date</p>
<ul style="list-style: none; padding: 0;">
<li>📖 <a href="./update/">Update Guide</a></li>
<li>💾 <a href="./advanced/database">Database Backup</a></li>
<li>🗑️ <a href="./advanced/uninstall">Uninstall Guide</a></li>
</ul>
</div>
<div style="background: #4a5568; border: 1px solid #d1d5da; border-radius: 8px; padding: 20px;">
<h3 style="margin-top: 0;">❓ Help & Support</h3>
<p>Troubleshooting and assistance</p>
<ul style="list-style: none; padding: 0;">
<li>🐛 <a href="./troubleshooting">Troubleshooting Guide</a></li>
<li>💬 <a href="https://discord.gg/DsaXMTEtpF">Discord Community</a></li>
<li>📝 <a href="https://github.com/aliasvault/aliasvault/issues">Report Issues</a></li>
</ul>
</div>
</div>
---
## Architecture Overview
The installer script deploys AliasVault as a multi-container application:
| Container | Purpose |
|-----------|---------|
| **reverse-proxy** | Nginx reverse proxy with SSL termination |
| **client** | Web interface (Blazor WebAssembly) |
| **api** | REST API backend |
| **admin** | Admin portal |
| **postgres** | PostgreSQL database |
| **smtp** | Email server for aliases |
| **task-runner** | Background jobs and maintenance |
All containers are managed via `./install.sh` (which uses `docker compose` in the background) and configured through a centralized `.env` file.

View File

@@ -1,29 +1,27 @@
---
layout: default
title: Basic Install
parent: Server Installation
title: Install Script
parent: Self-host Install
redirect_from:
- /installation/install
- /installation/install.html
nav_order: 1
---
# Basic Install
The following guide will walk you through the steps to install AliasVault on your own server. Minimum experience with Docker and Linux is required.
# Self-host using Install Script (multi-container)
The following guide will walk you through the steps to install AliasVault on your own server using the AliasVault installer script: `install.sh`. This script will pull pre-built Docker Images and do all the configuration for you while using `docker compose` in the background.
{: .toc }
* TOC
{:toc}
{: .important-title }
> Requirements:
> - 64-bit Linux VM with root access (Ubuntu or RHEL-based recommended)
> - Minimum: 1 vCPU, 1GB RAM, 16GB disk
> - Docker (CE ≥ 20.10) and Docker Compose (≥ 2.0)
> → Installation guide: [Docker Docs](https://docs.docker.com/engine/install/)
> - Able to forward ports 80, 443 (with optional 25/587 for private email domains)
---
## 1. Basic Installation
To get AliasVault up and running quickly, run the install script to pull pre-built Docker images. The install script will also configure the .env file and start the AliasVault containers. You can get up and running in less than 5 minutes.
### Hardware requirements
- 64-bit Linux VM with root access (Ubuntu or RHEL-based recommended)
- Minimum: 1 vCPU, 1GB RAM, 16GB disk
- Docker (CE ≥ 20.10) and Docker Compose (≥ 2.0)
→ Installation guide: [Docker Docs](https://docs.docker.com/engine/install/)
### Installation steps
1. Download the install script to a directory of your choice. All AliasVault files and directories will be created in this directory.
```bash
# Download the install script
@@ -45,14 +43,14 @@ chmod +x install.sh
- Client: `https://localhost`
- Admin: `https://localhost/admin`
> Note: if you do not wish to run the `install.sh` wizard but want to use Docker commands directly, follow the [manual setup guide](advanced/manual-setup.md). We do however encourage the use of `install.sh` as it will guide you through all configuration steps and allow you to easily update your AliasVault server later.
> Note: if you do not wish to run the `install.sh` wizard but prefer to use Docker commands directly, follow the [manual setup guide](../manual) instead.
---
## 2. SSL configuration
The default installation will create a self-signed SSL certificate and configure Nginx to use it.
## 2. TLS/SSL configuration
The default installation will create a self-signed TLS/SSL certificate and configure Nginx to use it. This is sufficient for local deployments using only the web-app, however the mobile apps (iOS and Android) require a valid (external) SSL certificate to be able to connect.
You can however also use Let's Encrypt to generate valid SSL certificates and configure Nginx to use it. In order to make this work you will need the following:
To generate a valid external TLS/SSL certificate for AliasVault, you can use Let's Encrypt via a built-in helper tool. In order to make this work you will need the following:
- A public IPv4 address assigned to your server
- Port 80 and 443 on your server must be open and accessible from the internet
@@ -66,29 +64,28 @@ You can however also use Let's Encrypt to generate valid SSL certificates and co
```
2. Follow the prompts to configure Let's Encrypt.
### Reverting to self-signed SSL
If at any point you would like to revert to the self-signed SSL certificate, run the install script again with the `configure-ssl` option
### Reverting to self-signed TLS/SSL
If at any point you would like to revert to the self-signed TLS/SSL certificate, run the install script again with the `configure-ssl` option
and then in the prompt choose option 2.
---
## 3. Email Server Setup
AliasVault includes a built-in email server that allows you to generate email aliases on-the-fly for every website you use, and receive the and read the emails straight in AliasVault.
AliasVault includes a built-in email server that allows you to generate email aliases on-the-fly for every website you use, and receive + read the emails straight in AliasVault.
> **Note:**
> If you skip this step, AliasVault will default to use public email domains offered by SpamOK. While this still works for creating aliases, it has privacy limitations. For complete privacy and control, we recommend setting up your own domain.
> [Learn more about the differences between private and public email domains](../misc/private-vs-public-email.md).
{: .note }
If you skip this step, AliasVault will default to use public email domains offered by SpamOK. While this still works for creating aliases, it has privacy limitations. For complete privacy and control, we recommend setting up your own domain. [Learn more about the differences between private and public email domains](../misc/private-vs-public-email.md).
---
### Requirements
- A **public IPv4 address** with ports 25 and 587 pointing to your AliasVault server
- Open ports **25** and **587** on your server firewall for email SMTP traffic.
- A **public IPv4 address** with ports 25 and 587 forwarded to your AliasVault server
- Open ports **25** and **587** on your server firewall for email SMTP traffic (*NOTE: some residential IP's block this, check with your ISP*).
#### Verifying Port Access
While the AliasVault docker containers are running, use `telnet` to confirm your public IP allows access to the ports:
While the AliasVault docker container is running, use `telnet` to confirm your public IP allows access to the ports:
```bash
# Test standard SMTP port

View File

@@ -1,7 +1,10 @@
---
layout: default
title: Troubleshooting
parent: Server Installation
parent: Install Script
redirect_from:
- /installation/troubleshooting
- /installation/troubleshooting.html
nav_order: 5
---
@@ -42,10 +45,10 @@ docker compose restart [container-name-here]
---
## Check AliasVault Text Logs
All AliasVault services log information and errors to text files. These files are located in the `logs` directory. You can check the logs of a specific container by running the following command:
All AliasVault services log information and errors to text files. These files are located in the `logs` directory. You can check the logs of a specific service by running the following command:
```bash
cat logs/[container-name-here].log
cat logs/[service-name-here].txt
```
---
@@ -70,13 +73,13 @@ docker compose ps
docker compose logs postgres
```
### 2. SSL Certificate Issues
### 2. TLS/SSL Certificate Issues
**Symptoms:**
- Browser shows SSL errors
- Browser shows TLS/SSL errors
**Steps:**
1. Check the certbot container logs if SSL certificates are being correctly renewed:
1. Check the certbot container logs if TLS/SSL certificates are being correctly renewed:
```bash
docker compose logs certbot
```
@@ -86,7 +89,7 @@ docker compose logs certbot
docker compose logs reverse-proxy
```
3. In case the SSL certificates are being correctly renewed, but the browser still shows SSL errors, try to restart AliasVault manually in order to force the NGINX container to reload the SSL certificates:
3. In case the SSL certificates are being correctly renewed, but the browser still shows TLS/SSL errors, try to restart AliasVault manually in order to force the NGINX container to reload the TLS/SSL certificates:
```bash
./install.sh restart
```
@@ -98,7 +101,7 @@ If you are not receiving emails on your aliases, check the following:
- Check your server's firewall settings
- Verify that your ISP/hosting provider allows SMTP traffic
Refer to the [installation guide](./install.md) for more information on how to configure your DNS records and ports.
Refer to the [installation guide](./#3-email-server-setup) for more information on how to configure your DNS records and ports.
### 4. Forgot AliasVault Admin Password
@@ -113,4 +116,4 @@ If you have lost your admin password, you can reset it by running the install sc
## Other Issues
If you encounter any other issues not mentioned here and need help, please join our Discord server or create an issue on the GitHub repository and we will be happy to help you out.
Find all contact information on the contact page of our website: [https://aliasvault.net/contact](https://aliasvault.net/contact)
Find all contact information on the contact page of our website: [https://www.aliasvault.net/contact](https://www.aliasvault.net/contact)

View File

@@ -1,7 +1,10 @@
---
layout: default
title: Update
parent: Server Installation
parent: Install Script
redirect_from:
- /installation/update
- /installation/update.html
nav_order: 3
---
@@ -36,6 +39,7 @@ For most version updates, you can use the standard update process:
## Version-Specific Upgrade Guides
Upgrading from certain earlier versions require additional steps during upgrade. If you are upgrading from an older version, please check the relevant articles below if it applies to your server:
- [Updating to 0.23.0](v0.23.0.html) - Update Docker Image locations due to new AliasVault GitHub organization
- [Updating to 0.22.0](v0.22.0.html) - Move secrets from .env to file based secrets
## Additional Update Options
@@ -56,5 +60,5 @@ To install a specific version and skip the automatic version checks, run the ins
./install.sh install <version>
# Example:
./install.sh install 0.7.0
./install.sh install 0.22.0
```

View File

@@ -2,8 +2,11 @@
layout: default
title: Update to v0.22.0
parent: Update
grand_parent: Server Installation
nav_order: 1
grand_parent: Install Script
redirect_from:
- /installation/update/v0.22.0
- /installation/update/v0.22.0.html
nav_order: 2
---
# Updating to v0.22.0

View File

@@ -0,0 +1,107 @@
---
layout: default
title: Update to v0.23.0
parent: Update
grand_parent: Install Script
redirect_from:
- /installation/update/v0.23.0
- /installation/update/v0.23.0.html
nav_order: 1
---
# Updating to v0.23.0
{: .no_toc }
Since v0.23.0, AliasVault has moved from `lanedirt/aliasvault` to the new `aliasvault/aliasvault` GitHub organization, and Docker image names have been simplified.
## Update Methods
### 1. Installed via install.sh
If you have installed AliasVault using the official `install.sh` method, you don't need to do anything. Running the built-in `install.sh update` command will take care of all necessary changes for you.
```bash
./install.sh update
```
### 2. Manually installed
If you have manually installed AliasVault via a custom `docker-compose.yml` file or other Docker management interface such as Portainer, you need to update your Docker image references.
#### Docker Image Name Changes
Update all Docker image references in your `docker-compose.yml` file according to this mapping:
| Old Image Name | New Image Name |
|----------------|----------------|
| ghcr.io/lanedirt/aliasvault-postgres | ghcr.io/aliasvault/postgres |
| ghcr.io/lanedirt/aliasvault-reverse-proxy | ghcr.io/aliasvault/reverse-proxy |
| ghcr.io/lanedirt/aliasvault-api | ghcr.io/aliasvault/api |
| ghcr.io/lanedirt/aliasvault-client | ghcr.io/aliasvault/client |
| ghcr.io/lanedirt/aliasvault-admin | ghcr.io/aliasvault/admin |
| ghcr.io/lanedirt/aliasvault-smtp | ghcr.io/aliasvault/smtp |
| ghcr.io/lanedirt/aliasvault-task-runner | ghcr.io/aliasvault/task-runner |
#### Example docker-compose.yml Update
**Before (v0.22.0 and earlier):**
```yaml
services:
postgres:
image: ghcr.io/lanedirt/aliasvault-postgres:0.22.0
reverse-proxy:
image: ghcr.io/lanedirt/aliasvault-reverse-proxy:0.22.0
api:
image: ghcr.io/lanedirt/aliasvault-api:0.22.0
client:
image: ghcr.io/lanedirt/aliasvault-client:0.22.0
admin:
image: ghcr.io/lanedirt/aliasvault-admin:0.22.0
smtp:
image: ghcr.io/lanedirt/aliasvault-smtp:0.22.0
task-runner:
image: ghcr.io/lanedirt/aliasvault-task-runner:0.22.0
```
**After (v0.23.0 and later):**
```yaml
services:
postgres:
image: ghcr.io/aliasvault/postgres:0.23.0
reverse-proxy:
image: ghcr.io/aliasvault/reverse-proxy:0.23.0
api:
image: ghcr.io/aliasvault/api:0.23.0
client:
image: ghcr.io/aliasvault/client:0.23.0
admin:
image: ghcr.io/aliasvault/admin:0.23.0
smtp:
image: ghcr.io/aliasvault/smtp:0.23.0
task-runner:
image: ghcr.io/aliasvault/task-runner:0.23.0
```
#### Update and restart
After updating your `docker-compose.yml`, pull the latest images and restart your containers:
```bash
docker-compose pull
docker-compose down
docker-compose up -d
```
If you encounter any issues during the upgrade, please join the AliasVault Discord, create an issue on GitHub or contact us by email.

View File

@@ -58,8 +58,7 @@ gunzip < aliasvault.sql.gz | docker compose exec -iT postgres psql -U aliasvault
```
### Change master password
By default during initial installation the PostgreSQL master password is set to a random string that is
stored in the `.env` file with the `POSTGRES_PASSWORD` variable.
By default during initial installation the PostgreSQL master password is set to a random string that is stored in the `./secrets/postgres_password` secret file.
If you wish to change the master password, you can do so by running the following command:
@@ -74,7 +73,7 @@ If you wish to change the master password, you can do so by running the followin
```
4. Press Enter to confirm the changes.
5. Exit the PostgreSQL shell by running `\q`.
6. Manually update the `.env` file variable `POSTGRES_PASSWORD` with the new password.
6. Manually update the `./secrets/postgres_password` secret file contents with the new password.
7. Restart the AliasVault containers by running the following command:
```bash
docker compose restart

View File

@@ -0,0 +1,65 @@
---
layout: page
title: Self-Signed SSL Setup
parent: Android App
grand_parent: Mobile Apps
nav_order: 3
---
# Self-Signed SSL Certificate Setup for Android
By default, the AliasVault Android app only supports connecting to servers with a valid SSL certificate from a trusted external authority. If you want to use your own self-signed certificate, you must manually install and trust the certificate on your Android device by following these steps.
## Server Setup
### Standard Installation
Configure your hostname and restart AliasVault:
```bash
./install.sh configure-hostname
./install.sh restart
```
### All-in-One Docker
Update your `docker-compose.yml`:
```yaml
environment:
HOSTNAME: "192.168.3.2" # Your server IP/hostname
```
Then restart: `docker compose down && docker compose up -d`
## Step 1: Get the Certificate
### Option A: From Browser
1. Open Chrome, go to your AliasVault instance (e.g., `https://192.168.3.2`)
2. Click the padlock icon → inspect certificate
3. Export the certificate and send it to your phone
### Option B: From Server
Copy from your AliasVault installation directory:
```bash
cp [aliasvault-install-dir]/certificates/ssl/cert.pem ~/aliasvault.crt
```
Transfer to your Android device.
## Step 2: Install Certificate (Android 10+)
1. **Open Settings** → search for "Certificate"
2. **Tap "Install a certificate"****"CA certificate"**
3. **Browse to Downloads** → select your certificate file
4. **Enter your PIN/password** when prompted
5. **Name it "AliasVault"** and tap **OK**
## Step 3: Configure AliasVault App
1. **Open the AliasVault app**
2. **Go to Settings****Server Configuration**
3. **Enter your server URL**: `https://192.168.3.2/api` (use your configured hostname)
4. **Test connection** - should work without SSL errors
## Troubleshooting
**Certificate not trusted**: Verify it's installed under Settings → Security → Trusted credentials → User tab
**App can't connect**: Ensure the hostname in the app matches your server configuration exactly
**Installation fails**: Make sure you have a screen lock set up on your device

View File

@@ -0,0 +1,71 @@
---
layout: page
title: Self-Signed SSL Setup
parent: iOS App
grand_parent: Mobile Apps
nav_order: 3
---
# Self-Signed SSL Certificate Setup for iOS
By default, the AliasVault iOS app only supports connecting to servers with a valid SSL certificate from a trusted external authority. If you want to use your own self-signed certificate, you must manually install and trust the certificate on your iOS device by following these steps.
## Server Setup
### Standard Installation
Configure your hostname and restart AliasVault:
```bash
./install.sh configure-hostname
./install.sh restart
```
### All-in-One Docker
Update your `docker-compose.yml`:
```yaml
environment:
HOSTNAME: "192.168.3.2" # Your server IP/hostname
```
Then restart: `docker compose down && docker compose up -d`
## Step 1: Get the Certificate
### Option A: From Browser
1. Open Chrome on your computer, go to your AliasVault instance (e.g., `https://192.168.3.2`)
2. Click the padlock icon → inspect certificate
3. Export the certificate and send it to your device (e.g. via email)
### Option B: From Server
Copy from your AliasVault installation directory:
```bash
cp [aliasvault-install-dir]/certificates/ssl/cert.pem ~/aliasvault.crt
```
## Step 2: Install Certificate Profile
1. Open the certificate on your iOS device
1. **Tap "Install"** in the top right corner
2. **Enter your passcode** when prompted
3. **Tap "Install"** again to confirm the warning
4. **Tap "Done"** when complete
## Step 3: Enable Certificate Trust (Critical!)
1. **Settings****General****About****Certificate Trust Settings**
2. **Find your certificate** (listed by hostname like "192.168.3.2")
3. **Toggle the switch to ON**
4. **Tap "Continue"** in the warning
## Step 4: Configure AliasVault App
1. **Open the AliasVault app**
2. **Go to Settings****Server Configuration**
3. **Enter your server URL**: `https://192.168.3.2/api` (use your configured hostname)
4. **Test connection** - should work without SSL errors
## Troubleshooting
**SSL errors**: Ensure you completed Step 3 (Certificate Trust) - this is the most commonly missed step
**Certificate Trust Settings not visible**: You must install a certificate profile first
**App can't connect**: Verify the hostname in the app matches your server configuration exactly

View File

@@ -871,9 +871,9 @@ main() {
if [ $? -eq 0 ]; then
printf "${CYAN}> Restarting admin container...${NC}\n"
if [ "$VERBOSE" = true ]; then
$(get_docker_compose_command) up -d --force-recreate admin
eval "$(get_docker_compose_command) up -d --force-recreate admin"
else
$(get_docker_compose_command) up -d --force-recreate admin > /dev/null 2>&1
eval "$(get_docker_compose_command) up -d --force-recreate admin" > /dev/null 2>&1
fi
print_password_reset_message
fi
@@ -1142,7 +1142,7 @@ create_env_file() {
populate_hostname() {
if ! grep -q "^HOSTNAME=" "$ENV_FILE" || [ -z "$(grep "^HOSTNAME=" "$ENV_FILE" | cut -d '=' -f2)" ]; then
while true; do
read -p "Enter the (public) hostname where this AliasVault server can be accessed from (e.g. aliasvault.net): " USER_HOSTNAME
read -p "Enter the hostname where this AliasVault server can be accessed (e.g. aliasvault.example.com): " USER_HOSTNAME
if [ -n "$USER_HOSTNAME" ]; then
HOSTNAME="$USER_HOSTNAME"
break
@@ -1583,13 +1583,13 @@ recreate_docker_containers() {
if [ "$VERBOSE" = true ]; then
printf "${CYAN} (Re)creating Docker containers...${NC}\n"
printf "\b${NC}\n"
if ! $(get_docker_compose_command) up -d --force-recreate; then
if ! eval "$(get_docker_compose_command) up -d --force-recreate"; then
log_error "Failed to recreate Docker containers"
exit 1
fi
else
(
$(get_docker_compose_command) up -d --force-recreate > /tmp/docker_recreate.log 2>&1 &
eval "$(get_docker_compose_command) up -d --force-recreate" > /tmp/docker_recreate.log 2>&1 &
RECREATE_PID=$!
show_spinner $RECREATE_PID "Recreating Docker containers "
wait $RECREATE_PID
@@ -1793,13 +1793,13 @@ handle_build() {
if [ "$VERBOSE" = true ]; then
printf "${CYAN} Building Docker Compose stack...${NC}\n"
printf "\b${NC}\n"
if ! $(get_docker_compose_command) build; then
if ! eval "$(get_docker_compose_command) build"; then
log_error "Failed to build Docker Compose stack"
exit 1
fi
else
(
$(get_docker_compose_command) build > install_compose_build_output.log 2>&1 &
eval "$(get_docker_compose_command) build" > install_compose_build_output.log 2>&1 &
BUILD_PID=$!
show_spinner $BUILD_PID "Building Docker Compose stack "
wait $BUILD_PID
@@ -1936,7 +1936,7 @@ handle_ssl_configuration() {
printf "Hostname: ${CYAN}${CURRENT_HOSTNAME}${NC} (change via: ./install.sh configure-hostname)\n"
printf "\n"
printf "Choose an option:\n"
printf "1) Use Let's Encrypt certificate (recommended)\n"
printf "1) Use Let's Encrypt certificate (recommended for public domains)\n"
printf "2) Use self-signed certificate\n"
printf "3) Cancel\n"
printf "\n"
@@ -2192,11 +2192,11 @@ configure_letsencrypt() {
# Restart only the reverse proxy with new configuration so it loads the new certificate
printf "${CYAN}> Restarting reverse proxy with Let's Encrypt configuration...${NC}\n"
$(get_docker_compose_command) up -d reverse-proxy --force-recreate
eval "$(get_docker_compose_command) up -d reverse-proxy --force-recreate"
# Starting certbot container to renew certificates automatically
printf "${CYAN}> Starting new certbot container to renew certificates automatically...${NC}\n"
$(get_docker_compose_command) up -d certbot
eval "$(get_docker_compose_command) up -d certbot"
# Print success message
printf "\n"
@@ -2210,17 +2210,27 @@ generate_self_signed_cert() {
# Disable Let's Encrypt
update_env_var "LETSENCRYPT_ENABLED" "false"
# Get current hostname from .env
HOSTNAME_VALUE=$(grep "^HOSTNAME=" "$ENV_FILE" | cut -d '=' -f2)
if [ -n "$HOSTNAME_VALUE" ] && [ "$HOSTNAME_VALUE" != "localhost" ]; then
printf "${CYAN}> Using configured hostname: ${HOSTNAME_VALUE}${NC}\n"
printf "${CYAN}> The certificate will include:${NC}\n"
printf " ${GREEN}Primary CN:${NC} ${HOSTNAME_VALUE}\n"
printf " ${GREEN}Alternative Names:${NC} localhost, 127.0.0.1\n\n"
fi
# Stop existing containers
printf "${CYAN}> Stopping existing containers...${NC}\n"
docker compose down
# Remove existing certificates
rm -f ./certificates/ssl/cert.pem ./certificates/ssl/key.pem
# Remove existing certificates and hostname marker
rm -f ./certificates/ssl/cert.pem ./certificates/ssl/key.pem ./certificates/ssl/.hostname_marker
# Remove Let's Encrypt directories
rm -rf ./certificates/letsencrypt
# Start containers (which will generate new self-signed certs)
# Start containers (which will generate new self-signed cert with hostname)
printf "${CYAN}> Restarting services...${NC}\n"
docker compose up -d
@@ -2232,7 +2242,7 @@ generate_self_signed_cert() {
# New functions to handle container lifecycle:
handle_start() {
printf "${CYAN}> Starting AliasVault containers...${NC}\n"
$(get_docker_compose_command) up -d
eval "$(get_docker_compose_command) up -d"
printf "${GREEN}> AliasVault containers started successfully.${NC}\n"
}
@@ -2243,14 +2253,14 @@ handle_stop() {
exit 0
fi
$(get_docker_compose_command) down
eval "$(get_docker_compose_command) down"
printf "${GREEN}> AliasVault containers stopped successfully.${NC}\n"
}
handle_restart() {
printf "\n${CYAN}> Restarting AliasVault containers...${NC}\n"
$(get_docker_compose_command) down
$(get_docker_compose_command) up -d
eval "$(get_docker_compose_command) down"
eval "$(get_docker_compose_command) up -d"
printf "${GREEN}> AliasVault containers restarted successfully.${NC}\n"
}
@@ -2727,9 +2737,10 @@ handle_db_export() {
printf "Options:\n" >&2
printf " --dev Export from development database\n" >&2
printf "\n" >&2
printf "Example:\n" >&2
printf "Examples:\n" >&2
printf " ./install.sh db-export > my_backup_$(date +%Y%m%d).sql.gz\n" >&2
printf " ./install.sh db-export --dev > my_dev_backup_$(date +%Y%m%d).sql.gz\n" >&2
printf "\n" >&2
exit 1
fi
@@ -2791,7 +2802,15 @@ handle_db_import() {
# Check if we're getting input from a pipe
if [ -t 0 ]; then
printf "Usage: ./install.sh db-import [--dev] < backup.sql.gz\n"
printf "Usage: ./install.sh db-import [--dev] < backup_file\n"
printf "\n"
printf "Options:\n"
printf " --dev Import to development database\n"
printf "\n"
printf "Examples:\n"
printf " ./install.sh db-import < backup.sql.gz # Import gzipped backup\n"
printf " ./install.sh db-import < backup.sql # Import plain SQL backup\n"
printf " ./install.sh db-import --dev < backup.sql # Import to dev database\n"
exit 1
fi
@@ -2840,15 +2859,25 @@ handle_db_import() {
fi
printf "database...${NC}\n"
# Create a temporary file to verify the gzip input
# Create a temporary file to store the input
temp_file=$(mktemp)
cat <&3 > "$temp_file" # Read from fd 3 instead of stdin
exec 3<&- # Close fd 3
if ! gzip -t "$temp_file" 2>/dev/null; then
printf "${RED}Error: Input is not a valid gzip file${NC}\n"
rm "$temp_file"
exit 1
# Detect if the file is gzipped or plain SQL
is_gzipped=false
if gzip -t "$temp_file" 2>/dev/null; then
is_gzipped=true
printf "${CYAN}> Detected gzipped SQL backup${NC}\n"
else
# Check if it looks like SQL (basic validation)
if head -n 10 "$temp_file" | grep -qE '(^--|^CREATE |^INSERT |^ALTER |^DROP |^\\\\connect|^SET |^COMMENT |^GRANT |^REVOKE )'; then
printf "${CYAN}> Detected plain SQL backup${NC}\n"
else
printf "${RED}Error: Input is neither a valid gzip file nor a SQL file${NC}\n"
rm "$temp_file"
exit 1
fi
fi
if [ "$DEV_DB" = true ]; then
@@ -2856,24 +2885,40 @@ handle_db_import() {
docker compose -f dockerfiles/docker-compose.dev.yml -p aliasvault-dev exec -T postgres-dev psql -U aliasvault postgres -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'aliasvault' AND pid <> pg_backend_pid();" && \
docker compose -f dockerfiles/docker-compose.dev.yml -p aliasvault-dev exec -T postgres-dev psql -U aliasvault postgres -c "DROP DATABASE IF EXISTS aliasvault;" && \
docker compose -f dockerfiles/docker-compose.dev.yml -p aliasvault-dev exec -T postgres-dev psql -U aliasvault postgres -c "CREATE DATABASE aliasvault OWNER aliasvault;" && \
gunzip -c "$temp_file" | docker compose -f dockerfiles/docker-compose.dev.yml -p aliasvault-dev exec -T postgres-dev psql -U aliasvault aliasvault
if [ "$is_gzipped" = true ]; then
gunzip -c "$temp_file" | docker compose -f dockerfiles/docker-compose.dev.yml -p aliasvault-dev exec -T postgres-dev psql -U aliasvault aliasvault
else
cat "$temp_file" | docker compose -f dockerfiles/docker-compose.dev.yml -p aliasvault-dev exec -T postgres-dev psql -U aliasvault aliasvault
fi
else
docker compose -f dockerfiles/docker-compose.dev.yml -p aliasvault-dev exec -T postgres-dev psql -U aliasvault postgres -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'aliasvault' AND pid <> pg_backend_pid();" > /dev/null 2>&1 && \
docker compose -f dockerfiles/docker-compose.dev.yml -p aliasvault-dev exec -T postgres-dev psql -U aliasvault postgres -c "DROP DATABASE IF EXISTS aliasvault;" > /dev/null 2>&1 && \
docker compose -f dockerfiles/docker-compose.dev.yml -p aliasvault-dev exec -T postgres-dev psql -U aliasvault postgres -c "CREATE DATABASE aliasvault OWNER aliasvault;" > /dev/null 2>&1 && \
gunzip -c "$temp_file" | docker compose -f dockerfiles/docker-compose.dev.yml -p aliasvault-dev exec -T postgres-dev psql -U aliasvault aliasvault > /dev/null 2>&1
if [ "$is_gzipped" = true ]; then
gunzip -c "$temp_file" | docker compose -f dockerfiles/docker-compose.dev.yml -p aliasvault-dev exec -T postgres-dev psql -U aliasvault aliasvault > /dev/null 2>&1
else
cat "$temp_file" | docker compose -f dockerfiles/docker-compose.dev.yml -p aliasvault-dev exec -T postgres-dev psql -U aliasvault aliasvault > /dev/null 2>&1
fi
fi
else
if [ "$VERBOSE" = true ]; then
docker compose exec -T postgres psql -U aliasvault postgres -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'aliasvault' AND pid <> pg_backend_pid();" && \
docker compose exec -T postgres psql -U aliasvault postgres -c "DROP DATABASE IF EXISTS aliasvault;" && \
docker compose exec -T postgres psql -U aliasvault postgres -c "CREATE DATABASE aliasvault OWNER aliasvault;" && \
gunzip -c "$temp_file" | docker compose exec -T postgres psql -U aliasvault aliasvault
if [ "$is_gzipped" = true ]; then
gunzip -c "$temp_file" | docker compose exec -T postgres psql -U aliasvault aliasvault
else
cat "$temp_file" | docker compose exec -T postgres psql -U aliasvault aliasvault
fi
else
docker compose exec -T postgres psql -U aliasvault postgres -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'aliasvault' AND pid <> pg_backend_pid();" > /dev/null 2>&1 && \
docker compose exec -T postgres psql -U aliasvault postgres -c "DROP DATABASE IF EXISTS aliasvault;" > /dev/null 2>&1 && \
docker compose exec -T postgres psql -U aliasvault postgres -c "CREATE DATABASE aliasvault OWNER aliasvault;" > /dev/null 2>&1 && \
gunzip -c "$temp_file" | docker compose exec -T postgres psql -U aliasvault aliasvault > /dev/null 2>&1
if [ "$is_gzipped" = true ]; then
gunzip -c "$temp_file" | docker compose exec -T postgres psql -U aliasvault aliasvault > /dev/null 2>&1
else
cat "$temp_file" | docker compose exec -T postgres psql -U aliasvault aliasvault > /dev/null 2>&1
fi
fi
fi
@@ -2908,8 +2953,7 @@ handle_hostname_configuration() {
fi
printf "The hostname is the domain name where your AliasVault server will be accessible.\n"
printf "A valid hostname is required for Let's Encrypt SSL certificate generation.\n"
printf "The hostname must be a real domain that points to this server (not localhost).\n"
printf "This hostname will be used for both Let's Encrypt and self-signed certificates.\n"
printf "\n"
# Get current hostname
@@ -2919,7 +2963,7 @@ handle_hostname_configuration() {
# Ask for new hostname
while true; do
read -p "Enter new hostname (e.g. aliasvault.net): " NEW_HOSTNAME
read -p "Enter new hostname (e.g. aliasvault.example.com): " NEW_HOSTNAME
if [ -n "$NEW_HOSTNAME" ]; then
break
else
@@ -2927,9 +2971,36 @@ handle_hostname_configuration() {
fi
done
# Check if hostname changed
HOSTNAME_CHANGED=false
if [ "$CURRENT_HOSTNAME" != "$NEW_HOSTNAME" ]; then
HOSTNAME_CHANGED=true
fi
# Update the hostname
update_env_var "HOSTNAME" "$NEW_HOSTNAME"
# If using self-signed cert and hostname changed, offer to regenerate
if [ "$HOSTNAME_CHANGED" = true ]; then
LETSENCRYPT_ENABLED=$(grep "^LETSENCRYPT_ENABLED=" "$ENV_FILE" | cut -d '=' -f2)
if [ "$LETSENCRYPT_ENABLED" != "true" ]; then
printf "\n${YELLOW}Hostname changed. The self-signed certificate needs to be regenerated.${NC}\n"
read -p "Regenerate certificate now? (y/n): " REGEN_CERT
if [ "$REGEN_CERT" = "y" ] || [ "$REGEN_CERT" = "Y" ]; then
# Remove the hostname marker to force regeneration
rm -f ./certificates/ssl/.hostname_marker
printf "\n${YELLOW}Restarting services to regenerate certificate...${NC}\n"
handle_restart
else
printf "${YELLOW}Please restart services manually to apply the new certificate.${NC}\n"
fi
else
printf "\n${YELLOW}Note: You're using Let's Encrypt. Make sure the new hostname has proper DNS records.${NC}\n"
printf "${YELLOW}You may need to reconfigure Let's Encrypt for the new hostname.${NC}\n"
fi
fi
printf "\n"
print_success_box "Hostname updated successfully to ${NEW_HOSTNAME}!"
}