Compare commits

..

38 Commits
0.7.0 ... 0.8.0

Author SHA1 Message Date
Leendert de Borst
0fb5327f04 Merge pull request #413 from lanedirt/412-add-update-option-to-install-script
Add update option to install script
2024-11-25 14:41:17 +01:00
Leendert de Borst
57f6b0961c Update docs (#412) 2024-11-25 14:40:38 +01:00
Leendert de Borst
c1d70fe504 Add support for installing specific version (#412) 2024-11-25 14:39:04 +01:00
Leendert de Borst
4c379802fc Update docker compose build workflow (#412) 2024-11-25 14:38:45 +01:00
dependabot[bot]
6a9a98b7bf Bump Microsoft.IdentityModel.JsonWebTokens and Microsoft.IdentityModel.Tokens
Bumps [Microsoft.IdentityModel.JsonWebTokens](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) and [Microsoft.IdentityModel.Tokens](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet). These dependencies needed to be updated together.

Updates `Microsoft.IdentityModel.JsonWebTokens` from 8.2.0 to 8.2.1
- [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases)
- [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/compare/8.2.0...8.2.1)

Updates `Microsoft.IdentityModel.Tokens` from 8.2.1 to 8.2.1
- [Release notes](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases)
- [Changelog](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/compare/8.2.1...8.2.1)

---
updated-dependencies:
- dependency-name: Microsoft.IdentityModel.JsonWebTokens
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: Microsoft.IdentityModel.Tokens
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-25 14:27:22 +01:00
dependabot[bot]
d2705d0b92 Bump Microsoft.NET.Test.Sdk from 17.11.1 to 17.12.0
Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 17.11.1 to 17.12.0.
- [Release notes](https://github.com/microsoft/vstest/releases)
- [Changelog](https://github.com/microsoft/vstest/blob/main/docs/releases.md)
- [Commits](https://github.com/microsoft/vstest/compare/v17.11.1...v17.12.0)

---
updated-dependencies:
- dependency-name: Microsoft.NET.Test.Sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-25 14:27:09 +01:00
dependabot[bot]
fcd0397184 Bump Microsoft.Playwright.NUnit and NUnit
Bumps [Microsoft.Playwright.NUnit](https://github.com/microsoft/playwright-dotnet) and [NUnit](https://github.com/nunit/nunit). These dependencies needed to be updated together.

Updates `Microsoft.Playwright.NUnit` from 1.48.0 to 1.49.0
- [Release notes](https://github.com/microsoft/playwright-dotnet/releases)
- [Commits](https://github.com/microsoft/playwright-dotnet/compare/v1.48.0...v1.49.0)

Updates `NUnit` from 4.2.2 to 3.13.2
- [Release notes](https://github.com/nunit/nunit/releases)
- [Changelog](https://github.com/nunit/nunit/blob/main/CHANGES.md)
- [Commits](https://github.com/nunit/nunit/compare/4.2.2...v3.13.2)

---
updated-dependencies:
- dependency-name: Microsoft.Playwright.NUnit
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: NUnit
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-25 14:27:02 +01:00
Leendert de Borst
a8e35d5e1d Update install script with explicit update option (#412) 2024-11-25 14:26:25 +01:00
Leendert de Borst
cf459f748f Merge pull request #411 from lanedirt/407-reduce-unnecessary-warnings-in-logs
Fix various warnings in logs
2024-11-25 13:48:33 +01:00
Leendert de Borst
65a2bebd51 Update SQLite connection config (#407) 2024-11-25 13:34:28 +01:00
Leendert de Borst
22e29c6cf5 Move DataProtection to top of program.cs to prevent decryption errors (#407) 2024-11-25 13:34:13 +01:00
Leendert de Borst
6fd4f7d607 Log Smtp messages to information instead of warning (#407) 2024-11-25 11:30:10 +01:00
Leendert de Borst
dab4762e94 Always force recreate docker containers after install (#407) 2024-11-25 11:29:44 +01:00
Leendert de Borst
bb3d38f50e Consolidate docker build/publish (#407) 2024-11-25 11:29:28 +01:00
Leendert de Borst
c7f6375fbb Return bad request if no refresh token is provided (#407) 2024-11-22 23:01:36 +01:00
Leendert de Borst
197248a6ea Merge pull request #406 from lanedirt/323-customize-error-when-unhandled-error-occurs-in-webapp
Style blazor wasm exception message
2024-11-22 12:15:35 +01:00
Leendert de Borst
5de9a0b8d8 Style blazor wasm exception message (#323) 2024-11-22 10:48:43 +01:00
Leendert de Borst
8a99dbf705 Merge pull request #394 from lanedirt/359-back-button-should-not-be-visible-at-terms-and-conditions-step-during-user-create
Do not show back button on first step of user creation
2024-11-22 10:03:45 +01:00
Leendert de Borst
b6b3b88b1d Merge pull request #395 from lanedirt/358-do-not-show-expired-access-tokens-on-security-page-on-client
Only show non-expired refresh tokens on client
2024-11-22 10:03:39 +01:00
Leendert de Borst
0dc699ea54 Merge pull request #396 from lanedirt/371-tweak-client-body-and-footer-z-index
Fix body and footer overlap issue
2024-11-22 10:03:33 +01:00
Leendert de Borst
a228ccb904 Merge pull request #397 from lanedirt/363-client-logout-action-registers-as-failed-in-auth-log
Fix refresh token revoke bug
2024-11-22 10:03:28 +01:00
Leendert de Borst
398e4016dc Merge pull request #399 from lanedirt/398-only-use-installsh-for-testing-pull-deploy-in-github-actions
Download fresh install.sh to test pull deploy in GitHub Actions
2024-11-22 10:03:22 +01:00
Leendert de Borst
fd1e0c5d15 Merge pull request #404 from lanedirt/402-add-github-pages-documentation-website
Update README with new docs website
2024-11-22 01:21:27 +01:00
Leendert de Borst
e6ea0c51c8 Update README with new docs website (#402) 2024-11-22 01:21:11 +01:00
Leendert de Borst
38eef67207 Merge pull request #403 from lanedirt/402-add-github-pages-documentation-website
Update documentation
2024-11-22 00:41:03 +01:00
Leendert de Borst
7ce253e93d Update docs (#402) 2024-11-22 00:40:41 +01:00
Leendert de Borst
c519b80159 Merge pull request #401 from lanedirt/400-tweak-docker-compose-setup-to-not-use-static-network-name-to-prevent-conflicts
Remove static docker network name to prevent conflicts as its not needed
2024-11-21 22:37:16 +01:00
Leendert de Borst
e128bbf091 Remove static docker network name to prevent conflicts as its not needed (#400) 2024-11-21 22:36:15 +01:00
Leendert de Borst
04315b38ba Create CNAME 2024-11-21 20:41:12 +01:00
Leendert de Borst
0ee1b5e992 Download fresh install.sh to test pull deploy instead of checking out full repo (#398) 2024-11-21 19:53:04 +01:00
Leendert de Borst
b4b2dc3fe7 Fix refresh token revoke bug (#363) 2024-11-21 19:26:16 +01:00
Leendert de Borst
7ac9cdc9e7 Tweak body so it fully overlaps over absolutely positioned footer while scrolling (#371) 2024-11-21 18:14:14 +01:00
Leendert de Borst
9ba8bb183a Only show non-expired refresh tokens on client (#358) 2024-11-21 18:12:42 +01:00
Leendert de Borst
7ef8a12fb2 Do not show back button on first step of user creation (#359) 2024-11-21 17:33:19 +01:00
Leendert de Borst
ea7aba4ff4 Merge pull request #393 from lanedirt/391-download-letsencrypt-docker-compose-yml-file-for-quick-install
Add static docker compose network name
2024-11-20 17:52:37 +01:00
Leendert de Borst
aac9694d5d Add static network name (#391) 2024-11-20 17:52:11 +01:00
Leendert de Borst
06d7666265 Merge pull request #392 from lanedirt/391-download-letsencrypt-docker-compose-yml-file-for-quick-install
Update install.sh
2024-11-20 17:23:56 +01:00
Leendert de Borst
ca17759727 Update install.sh (#391) 2024-11-20 17:23:36 +01:00
64 changed files with 1234 additions and 254 deletions

View File

@@ -32,14 +32,14 @@ jobs:
- name: Wait for services to be up
run: |
# Wait for a few seconds
sleep 10
- name: Test if localhost:443 (WASM app) responds
uses: nick-fields/retry@v3
with:
timeout_minutes: 2
max_attempts: 3
command: |
http_code=$(curl -k -s -o /dev/null -w "%{http_code}" https://localhost:443)
sleep 15
- name: Test if localhost:443 (WASM app) responds
uses: nick-fields/retry@v3
with:
timeout_minutes: 2
max_attempts: 3
command: |
http_code=$(curl -k -s -o /dev/null -w "%{http_code}" https://localhost:443)
if [ "$http_code" -ne 200 ]; then
echo "Service did not respond with 200 OK. Check if client app and/or nginx is configured correctly."
exit 1
@@ -47,13 +47,13 @@ jobs:
echo "Service responded with 200 OK"
fi
- name: Test if localhost:443/api (WebApi) responds
uses: nick-fields/retry@v3
with:
timeout_minutes: 2
max_attempts: 3
command: |
http_code=$(curl -k -s -o /dev/null -w "%{http_code}" https://localhost:443/api)
- name: Test if localhost:443/api (WebApi) responds
uses: nick-fields/retry@v3
with:
timeout_minutes: 2
max_attempts: 3
command: |
http_code=$(curl -k -s -o /dev/null -w "%{http_code}" https://localhost:443/api)
if [ "$http_code" -ne 200 ]; then
echo "Service did not respond with expected 200 OK. Check if WebApi and/or nginx is configured correctly."
exit 1
@@ -61,32 +61,32 @@ jobs:
echo "Service responded with $http_code"
fi
- name: Test if localhost:443/admin (Admin) responds
uses: nick-fields/retry@v3
with:
timeout_minutes: 2
max_attempts: 3
command: |
http_code=$(curl -k -s -o /dev/null -w "%{http_code}" https://localhost:443/admin/user/login)
if [ "$http_code" -ne 200 ]; then
echo "Service did not respond with expected 200 OK. Check if admin app and/or nginx is configured correctly."
exit 1
else
echo "Service responded with $http_code"
fi
- name: Test if localhost:443/admin (Admin) responds
uses: nick-fields/retry@v3
with:
timeout_minutes: 2
max_attempts: 3
command: |
http_code=$(curl -k -s -o /dev/null -w "%{http_code}" https://localhost:443/admin/user/login)
if [ "$http_code" -ne 200 ]; then
echo "Service did not respond with expected 200 OK. Check if admin app and/or nginx is configured correctly."
exit 1
else
echo "Service responded with $http_code"
fi
- name: Test if localhost:2525 (SmtpService) responds
uses: nick-fields/retry@v3
with:
timeout_minutes: 2
max_attempts: 3
command: |
if ! nc -zv localhost 2525 2>&1 | grep -q 'succeeded'; then
echo "SmtpService did not respond on port 2525. Check if the SmtpService service is running."
exit 1
else
echo "SmtpService responded on port 2525"
fi
- name: Test if localhost:2525 (SmtpService) responds
uses: nick-fields/retry@v3
with:
timeout_minutes: 2
max_attempts: 3
command: |
if ! nc -zv localhost 2525 2>&1 | grep -q 'succeeded'; then
echo "SmtpService did not respond on port 2525. Check if the SmtpService service is running."
exit 1
else
echo "SmtpService responded on port 2525"
fi
- name: Test install.sh reset-password output
run: |

View File

@@ -17,7 +17,18 @@ jobs:
options: --privileged
steps:
- uses: actions/checkout@v2
- name: Get repository and branch information
id: repo-info
run: |
echo "REPO_FULL_NAME=${GITHUB_REPOSITORY}" >> $GITHUB_ENV
echo "BRANCH_NAME=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_ENV
- name: Download install script from current branch
run: |
INSTALL_SCRIPT_URL="https://raw.githubusercontent.com/$REPO_FULL_NAME/$BRANCH_NAME/install.sh"
echo "Downloading install script from: $INSTALL_SCRIPT_URL"
curl -f -o install.sh "$INSTALL_SCRIPT_URL"
- name: Set permissions and run install.sh
run: |
chmod +x install.sh

5
.gitignore vendored
View File

@@ -399,3 +399,8 @@ certificates/**/*.key
certificates/**/*.pfx
certificates/**/*.pem
certificates/letsencrypt/**
# Docs
docs/_site
docs/vendor
docs/.bundle

View File

@@ -3,7 +3,7 @@
<h1><img src="https://github.com/user-attachments/assets/933c8b45-a190-4df6-913e-b7c64ad9938b" width="40" /> AliasVault</h1>
<p align="center">
<a href="https://app.aliasvault.net">Live demo 🚀</a> • <a href="https://aliasvault.net?utm_source=gh-readme">Website 🏠</a> • <a href="#installation">Installation 📦</a>
<a href="https://app.aliasvault.net">Live demo 🔥</a> • <a href="https://aliasvault.net?utm_source=gh-readme">Website 🌐</a> • <a href="https://docs.aliasvault.net?utm_source=gh-readme">Documentation 📚</a> • <a href="#installation">Installation ⚙️</a>
</p>
<h3 align="center">
@@ -19,6 +19,12 @@ Open-source password and alias manager
[<img src="https://img.shields.io/sonar/quality_gate/lanedirt_AliasVault?server=https%3A%2F%2Fsonarcloud.io&label=sonarcloud&logo=sonarcloud">](https://sonarcloud.io/summary/new_code?id=lanedirt_AliasVault)
</div>
<div align="center">
[<img alt="Discord" src="https://img.shields.io/discord/1309300619026235422?logo=discord&logoColor=%237289da&label=join%20discord%20chat&color=%237289da">](https://discord.gg/DsaXMTEtpF)
</div>
AliasVault is an open-source password and alias manager built with C# ASP.NET technology. AliasVault can be self-hosted on your own server with Docker, providing a secure and private solution for managing your online identities and passwords.
### What makes AliasVault unique:
@@ -32,19 +38,20 @@ AliasVault is an open-source password and alias manager built with C# ASP.NET te
## Live demo
A live demo of the app is available at the official website at [app.aliasvault.net](https://app.aliasvault.net) (up-to-date with `main` branch). You can create a free account to try it out yourself.
<img width="700" alt="Screenshot of AliasVault" src="docs/img/screenshot.png">
<img width="700" alt="Screenshot of AliasVault" src="docs/assets/img/screenshot.png">
## Installation
Choose one of the following installation methods:
To install AliasVault, the easiest method is to use the provided install script. This will download the pre-built Docker images and start the containers.
### Option 1: Quick Install (Pre-built Images)
### 1. Install using install script
This method uses pre-built Docker images and works on minimal hardware specifications:
- Linux (Ubuntu or RHEL based distros recommended)
- 512MB RAM
- Linux VM with root access (Ubuntu or RHEL based distros recommended)
- 1 vCPU
- At least 16GB disk space
- 512MB RAM
- 16GB disk space
- Docker installed
```bash
@@ -56,28 +63,7 @@ chmod +x install.sh
./install.sh install
```
### Option 2: Build from Source
Building from source requires more resources:
- Minimum 2GB RAM (more RAM will speed up build time)
- At least 1 vCPU
- 40GB+ disk space (for dependencies and build artifacts)
- Docker installed
- Git installed
```bash
# Clone the repository
git clone https://github.com/lanedirt/AliasVault.git
cd AliasVault
# Make build script executable and run it. This will create the .env file, build the Docker images from source, and start the AliasVault containers.
chmod +x install.sh
./install.sh build
```
Note: If you do not wish to run the script, you can set up the environment variables and build the Docker image and containers manually instead. See the [manual setup instructions](docs/install/1-manually-setup-docker.md) for more information.
### Post-Installation
### 2. Post-Installation
The install script will output the URL where the app is available. By default this is:
- Client: https://localhost
@@ -85,17 +71,15 @@ The install script will output the URL where the app is available. By default th
> Note: If you want to change the default AliasVault ports you can do so in the `docker-compose.yml` file for the `nginx` (reverse-proxy) container.
#### First Time Setup Notes:
- When building from source for the first time, it may take several minutes for Docker to download and compile all dependencies. Subsequent builds will be faster.
- A SQLite database file will be created in `./database/AliasServerDb.sqlite`. This file will store all (encrypted) password vaults. It should be kept secure and not shared.
## Detailed documentation
For more detailed information about the installation process and other topics, please see the official documentation website:
- [Documentation website (docs.aliasvault.net) 📚](https://docs.aliasvault.net)
#### Useful Commands:
- To reset the admin password: `./install.sh reset-password`
- To uninstall AliasVault: `./install.sh uninstall`
This will remove all containers, images, and volumes related to AliasVault while keeping configuration files intact for future reinstallation.
- If something goes wrong you can run the install script in verbose mode to get more information: `./install.sh [command] --verbose`
Here you can also find step-by-step instructions on how to install AliasVault to e.g. Azure, AWS and other popular cloud providers.
## Security Architecture
<a href="https://docs.aliasvault.net/architecture"><img alt="AliasVault Security Architecture Diagram" src="docs/assets/diagrams/security-architecture/aliasvault-security-architecture-thumb.jpg" width="343"></a>
AliasVault takes security seriously and implements various measures to protect your data:
- All sensitive user data is encrypted end-to-end using industry-standard encryption algorithms. This includes the complete vault contents and all received emails.
@@ -104,7 +88,9 @@ AliasVault takes security seriously and implements various measures to protect y
For detailed information about our encryption implementation and security architecture, see the following documents:
- [SECURITY.md](SECURITY.md)
- [Security Architecture Diagram](docs/security-architecture.md)
- [Security Architecture Diagram](https://docs.aliasvault.net/architecture)
## Tech stack / credits
The following technologies, frameworks and libraries are used in this project:

View File

@@ -19,7 +19,7 @@ The following encryption algorithms are used by AliasVault:
Below is a detailed explanation of each encryption algorithm.
For more information about how these algorithms are specifically used in AliasVault, see the [Security Architecture](docs/security-architecture.md) document.
For more information about how these algorithms are specifically used in AliasVault, see the [Architecture Documentation](https://docs.aliasvault.net/architecture) section on the documentation site.
### Argon2id
To derive a key from the master password, AliasVault uses the Argon2id key derivation function. Argon2id is a memory-hard

View File

@@ -62,7 +62,3 @@ services:
env_file:
- .env
restart: always
networks:
aliasvault:
name: aliasvault_default

1
docs/CNAME Normal file
View File

@@ -0,0 +1 @@
docs.aliasvault.net

8
docs/Dockerfile Normal file
View File

@@ -0,0 +1,8 @@
FROM jekyll/jekyll:4.2.2
WORKDIR /srv/jekyll
COPY . .
RUN chown -R jekyll:jekyll /srv/jekyll
# Install the theme and dependencies
RUN bundle install

8
docs/Gemfile Normal file
View File

@@ -0,0 +1,8 @@
source 'https://rubygems.org'
# gem "jekyll", "~> 4.3.2"
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

286
docs/Gemfile.lock Normal file
View File

@@ -0,0 +1,286 @@
GEM
remote: https://rubygems.org/
specs:
activesupport (7.2.2)
base64
benchmark (>= 0.3)
bigdecimal
concurrent-ruby (~> 1.0, >= 1.3.1)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
logger (>= 1.4.2)
minitest (>= 5.1)
securerandom (>= 0.3)
tzinfo (~> 2.0, >= 2.0.5)
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
base64 (0.2.0)
benchmark (0.4.0)
bigdecimal (3.1.8)
coffee-script (2.4.1)
coffee-script-source
execjs
coffee-script-source (1.12.2)
colorator (1.1.0)
commonmarker (0.23.11)
concurrent-ruby (1.3.4)
connection_pool (2.4.1)
csv (3.3.0)
dnsruby (1.72.3)
base64 (~> 0.2.0)
simpleidn (~> 0.2.1)
drb (2.2.1)
em-websocket (0.5.3)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0)
ethon (0.16.0)
ffi (>= 1.15.0)
eventmachine (1.2.7)
execjs (2.10.0)
faraday (2.12.1)
faraday-net_http (>= 2.0, < 3.5)
json
logger
faraday-net_http (3.4.0)
net-http (>= 0.5.0)
ffi (1.17.0-x86_64-linux-musl)
forwardable-extended (2.6.0)
gemoji (4.1.0)
github-pages (232)
github-pages-health-check (= 1.18.2)
jekyll (= 3.10.0)
jekyll-avatar (= 0.8.0)
jekyll-coffeescript (= 1.2.2)
jekyll-commonmark-ghpages (= 0.5.1)
jekyll-default-layout (= 0.1.5)
jekyll-feed (= 0.17.0)
jekyll-gist (= 1.5.0)
jekyll-github-metadata (= 2.16.1)
jekyll-include-cache (= 0.2.1)
jekyll-mentions (= 1.6.0)
jekyll-optional-front-matter (= 0.3.2)
jekyll-paginate (= 1.1.0)
jekyll-readme-index (= 0.3.0)
jekyll-redirect-from (= 0.16.0)
jekyll-relative-links (= 0.6.1)
jekyll-remote-theme (= 0.4.3)
jekyll-sass-converter (= 1.5.2)
jekyll-seo-tag (= 2.8.0)
jekyll-sitemap (= 1.4.0)
jekyll-swiss (= 1.0.0)
jekyll-theme-architect (= 0.2.0)
jekyll-theme-cayman (= 0.2.0)
jekyll-theme-dinky (= 0.2.0)
jekyll-theme-hacker (= 0.2.0)
jekyll-theme-leap-day (= 0.2.0)
jekyll-theme-merlot (= 0.2.0)
jekyll-theme-midnight (= 0.2.0)
jekyll-theme-minimal (= 0.2.0)
jekyll-theme-modernist (= 0.2.0)
jekyll-theme-primer (= 0.6.0)
jekyll-theme-slate (= 0.2.0)
jekyll-theme-tactile (= 0.2.0)
jekyll-theme-time-machine (= 0.2.0)
jekyll-titles-from-headings (= 0.5.3)
jemoji (= 0.13.0)
kramdown (= 2.4.0)
kramdown-parser-gfm (= 1.1.0)
liquid (= 4.0.4)
mercenary (~> 0.3)
minima (= 2.5.1)
nokogiri (>= 1.16.2, < 2.0)
rouge (= 3.30.0)
terminal-table (~> 1.4)
webrick (~> 1.8)
github-pages-health-check (1.18.2)
addressable (~> 2.3)
dnsruby (~> 1.60)
octokit (>= 4, < 8)
public_suffix (>= 3.0, < 6.0)
typhoeus (~> 1.3)
html-pipeline (2.14.3)
activesupport (>= 2)
nokogiri (>= 1.4)
http_parser.rb (0.8.0)
i18n (1.14.6)
concurrent-ruby (~> 1.0)
jekyll (3.10.0)
addressable (~> 2.4)
colorator (~> 1.0)
csv (~> 3.0)
em-websocket (~> 0.5)
i18n (>= 0.7, < 2)
jekyll-sass-converter (~> 1.0)
jekyll-watch (~> 2.0)
kramdown (>= 1.17, < 3)
liquid (~> 4.0)
mercenary (~> 0.3.3)
pathutil (~> 0.9)
rouge (>= 1.7, < 4)
safe_yaml (~> 1.0)
webrick (>= 1.0)
jekyll-avatar (0.8.0)
jekyll (>= 3.0, < 5.0)
jekyll-coffeescript (1.2.2)
coffee-script (~> 2.2)
coffee-script-source (~> 1.12)
jekyll-commonmark (1.4.0)
commonmarker (~> 0.22)
jekyll-commonmark-ghpages (0.5.1)
commonmarker (>= 0.23.7, < 1.1.0)
jekyll (>= 3.9, < 4.0)
jekyll-commonmark (~> 1.4.0)
rouge (>= 2.0, < 5.0)
jekyll-default-layout (0.1.5)
jekyll (>= 3.0, < 5.0)
jekyll-feed (0.17.0)
jekyll (>= 3.7, < 5.0)
jekyll-gist (1.5.0)
octokit (~> 4.2)
jekyll-github-metadata (2.16.1)
jekyll (>= 3.4, < 5.0)
octokit (>= 4, < 7, != 4.4.0)
jekyll-include-cache (0.2.1)
jekyll (>= 3.7, < 5.0)
jekyll-mentions (1.6.0)
html-pipeline (~> 2.3)
jekyll (>= 3.7, < 5.0)
jekyll-optional-front-matter (0.3.2)
jekyll (>= 3.0, < 5.0)
jekyll-paginate (1.1.0)
jekyll-readme-index (0.3.0)
jekyll (>= 3.0, < 5.0)
jekyll-redirect-from (0.16.0)
jekyll (>= 3.3, < 5.0)
jekyll-relative-links (0.6.1)
jekyll (>= 3.3, < 5.0)
jekyll-remote-theme (0.4.3)
addressable (~> 2.0)
jekyll (>= 3.5, < 5.0)
jekyll-sass-converter (>= 1.0, <= 3.0.0, != 2.0.0)
rubyzip (>= 1.3.0, < 3.0)
jekyll-sass-converter (1.5.2)
sass (~> 3.4)
jekyll-seo-tag (2.8.0)
jekyll (>= 3.8, < 5.0)
jekyll-sitemap (1.4.0)
jekyll (>= 3.7, < 5.0)
jekyll-swiss (1.0.0)
jekyll-theme-architect (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-cayman (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-dinky (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-hacker (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-leap-day (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-merlot (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-midnight (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-minimal (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-modernist (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-primer (0.6.0)
jekyll (> 3.5, < 5.0)
jekyll-github-metadata (~> 2.9)
jekyll-seo-tag (~> 2.0)
jekyll-theme-slate (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-tactile (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-time-machine (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-titles-from-headings (0.5.3)
jekyll (>= 3.3, < 5.0)
jekyll-watch (2.2.1)
listen (~> 3.0)
jemoji (0.13.0)
gemoji (>= 3, < 5)
html-pipeline (~> 2.2)
jekyll (>= 3.0, < 5.0)
json (2.8.2)
just-the-docs (0.10.0)
jekyll (>= 3.8.5)
jekyll-include-cache
jekyll-seo-tag (>= 2.0)
rake (>= 12.3.1)
kramdown (2.4.0)
rexml
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
liquid (4.0.4)
listen (3.9.0)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
logger (1.6.1)
mercenary (0.3.6)
minima (2.5.1)
jekyll (>= 3.5, < 5.0)
jekyll-feed (~> 0.9)
jekyll-seo-tag (~> 2.1)
minitest (5.25.1)
net-http (0.5.0)
uri
nokogiri (1.16.7-x86_64-linux)
racc (~> 1.4)
octokit (4.25.1)
faraday (>= 1, < 3)
sawyer (~> 0.9)
pathutil (0.16.2)
forwardable-extended (~> 2.6)
public_suffix (5.1.1)
racc (1.8.1)
rake (13.2.1)
rb-fsevent (0.11.2)
rb-inotify (0.11.1)
ffi (~> 1.0)
rexml (3.3.9)
rouge (3.30.0)
rubyzip (2.3.2)
safe_yaml (1.0.5)
sass (3.7.4)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
sawyer (0.9.2)
addressable (>= 2.3.5)
faraday (>= 0.17.3, < 3)
securerandom (0.3.2)
simpleidn (0.2.3)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
typhoeus (1.4.1)
ethon (>= 0.9.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (1.8.0)
uri (1.0.2)
webrick (1.9.0)
PLATFORMS
x86_64-linux-musl
DEPENDENCIES
github-pages
just-the-docs
BUNDLED WITH
2.3.25

View File

@@ -1,5 +0,0 @@
# Documentation
This is the documentation for the AliasVault project.
## Description
TODO: Work in progress.

40
docs/_config.yml Normal file
View File

@@ -0,0 +1,40 @@
remote_theme: just-the-docs/just-the-docs
title: AliasVault
description: Documentation for the AliasVault password manager
logo: "/assets/img/logo.svg"
favicon_ico: "/assets/img/favicon.png"
# Navigation settings
aux_links:
"AliasVault on GitHub":
- "https://github.com/lanedirt/AliasVault"
"AliasVault Website":
- "https://aliasvault.net"
aux_links_new_tab: true
# Search settings
search_enabled: true
heading_anchors: true
# Theme settings
color_scheme: aliasvault
# Enable copy code button
enable_copy_code_button: true
# Footer "Edit this page on GitHub" link text
gh_edit_link: true # show or hide edit this page link
gh_edit_link_text: "Edit this page on GitHub."
gh_edit_repository: "https://github.com/lanedirt/AliasVault" # the github URL for your repo
gh_edit_branch: "main" # the branch that your docs is served from
gh_edit_source: docs # the source that your files originate from
gh_edit_view_mode: "tree" # "tree" or "edit" if you want the user to jump into the editor immediately
callouts:
warning:
title: Warning
color: red
note:
title: Note
color: purple

View File

View File

@@ -0,0 +1 @@
&nbsp;

View File

@@ -0,0 +1,42 @@
@import "./color_schemes/dark";
// Base theme colors
$link-color: #f49541;
$btn-primary-color: #d68338;
// Main colors
$body-background-color: #1f2937;
$sidebar-color: #111827;
$border-color: #374151;
$body-text-color: #f8f9fa;
// Navigation
$nav-child-link-color: #fdde85;
$search-result-preview-color: #e9ecef;
// Content elements
$feedback-color: #2d3748;
$table-background-color: #374151;
$search-background-color: #374151;
// Code blocks
$code-background-color: #2d3748;
$code-linenumber-color: #9ca3af;
// Tables
$table-border-color: #4b5563;
// Search
$search-result-preview-color: #d1d5db;
// Buttons
$btn-primary-color-dark: #d68338;
// Base Colors (kept for compatibility)
$purple-000: #f8b963;
$purple-100: #ffd5a8;
$purple-200: #f49541;
$purple-300: #d68338;
// Navigation additional
$nav-button-color: #f49541;

View File

@@ -1,4 +1,11 @@
# Security Architecture
---
layout: default
title: Architecture
has_children: true
nav_order: 3
---
# Architecture
AliasVault implements a zero-knowledge architecture where sensitive user data and passwords never leave the client device in unencrypted form. Below is a detailed explanation of how the system secures user data and communications.
@@ -6,12 +13,12 @@ AliasVault implements a zero-knowledge architecture where sensitive user data an
The security architecture diagram below illustrates all encryption and authentication processes used in AliasVault to secure user data and communications.
<picture>
<source media="(prefers-color-scheme: dark)" srcset="diagrams/security-architecture/aliasvault-security-architecture-dark.svg">
<source media="(prefers-color-scheme: light)" srcset="diagrams/security-architecture/aliasvault-security-architecture-light.svg">
<img alt="AliasVault Security Architecture Diagram" src="diagrams/security-architecture/aliasvault-security-architecture-light.svg">
<source media="(prefers-color-scheme: dark)" srcset="../assets/diagrams/security-architecture/aliasvault-security-architecture-dark.svg">
<source media="(prefers-color-scheme: light)" srcset="../assets/diagrams/security-architecture/aliasvault-security-architecture-light.svg">
<img alt="AliasVault Security Architecture Diagram" src="../assets/diagrams/security-architecture/aliasvault-security-architecture-light.svg">
</picture>
You can also view the diagram in a browser-friendly HTML format: [AliasVault Security Architecture](diagrams/security-architecture/aliasvault-security-architecture.html)
You can also view the diagram in a browser-friendly HTML format: [AliasVault Security Architecture](https://lanedirt.github.io/AliasVault/assets/diagrams/security-architecture/aliasvault-security-architecture.html)
## Key Components and Process Flow

View File

@@ -1,3 +1,5 @@
# Diagrams
This folder contains architecture and flow diagrams for AliasVault in various formats.

View File

Before

Width:  |  Height:  |  Size: 1024 KiB

After

Width:  |  Height:  |  Size: 1024 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

BIN
docs/assets/img/favicon.png Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 936 B

2
docs/assets/img/logo.svg Normal file
View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<svg enable-background="new 0 0 800 500" version="1.1" viewBox="-1.84 7.892 1822.253 474.315" xmlns="http://www.w3.org/2000/svg" xmlns:bx="https://boxy-svg.com" width="1822.253px" height="474.315px"><defs><bx:export><bx:file format="svg"/></bx:export></defs><path d="m459.87 294.95c0.016205 5.4005 0.03241 10.801-0.35022 16.873-1.111 6.3392-1.1941 12.173-2.6351 17.649-10.922 41.508-36.731 69.481-77.351 83.408-7.2157 2.4739-14.972 3.3702-22.479 4.995-23.629 0.042205-47.257 0.11453-70.886 0.12027-46.762 0.011322-93.523-0.01416-140.95-0.43411-8.59-2.0024-16.766-2.8352-24.398-5.3326-21.595-7.0666-39.523-19.656-53.708-37.552-10.227-12.903-17.579-27.17-21.28-43.221-1.475-6.3967-2.4711-12.904-3.6852-19.361-0.051849-5.747-0.1037-11.494 0.26915-17.886 4.159-42.973 27.68-71.638 63.562-92.153 0-0.70761-0.001961-1.6988 3.12e-4 -2.69 0.022484-9.8293-1.3071-19.894 0.35664-29.438 3.2391-18.579 11.08-35.272 23.763-49.773 12.098-13.832 26.457-23.989 43.609-30.029 7.813-2.7512 16.14-4.0417 24.234-5.9948 7.392-0.025734 14.784-0.05146 22.835 0.32253 4.1959 0.95392 7.7946 1.2538 11.258 2.1053 17.16 4.2192 32.287 12.176 45.469 24.104 2.2558 2.0411 4.372 6.6241 9.621 3.868 16.839-8.8419 34.718-11.597 53.603-8.594 16.791 2.6699 31.602 9.4308 44.236 20.636 11.531 10.227 19.84 22.841 25.393 37.236 6.3436 16.445 10.389 33.163 6.0798 49.389 7.9587 8.9321 15.807 16.704 22.421 25.414 9.162 12.065 15.33 25.746 18.144 40.776 0.97046 5.1848 1.9111 10.375 2.8654 15.563m-71.597 71.012c5.5615-5.2284 12.002-9.7986 16.508-15.817 10.474-13.992 14.333-29.916 11.288-47.446-2.2496-12.95-8.1973-24.076-17.243-33.063-12.746-12.663-28.865-18.614-46.786-18.569-69.912 0.17712-139.82 0.56831-209.74 0.96176-15.922 0.089599-29.168 7.4209-39.685 18.296-14.45 14.944-20.408 33.343-16.655 54.368 2.2763 12.754 8.2167 23.748 17.158 32.66 13.299 13.255 30.097 18.653 48.728 18.651 59.321-0.005188 118.64 0.042358 177.96-0.046601 9.5912-0.014374 19.181-0.86588 28.773-0.88855 10.649-0.025146 19.978-3.825 29.687-9.1074z" fill="#EEC170"/><path d="m162.77 293c15.654 4.3883 20.627 22.967 10.304 34.98-5.3104 6.1795-14.817 8.3208-24.278 5.0472-7.0723-2.4471-12.332-10.362-12.876-17.933-1.0451-14.542 11.089-23.176 21.705-23.046 1.5794 0.019287 3.1517 0.61566 5.1461 0.95184z" fill="#EEC170"/><path d="m227.18 293.64c7.8499 2.3973 11.938 8.2143 13.524 15.077 1.8591 8.0439-0.44817 15.706-7.1588 21.121-6.7633 5.4572-14.417 6.8794-22.578 3.1483-8.2972-3.7933-12.836-10.849-12.736-19.438 0.1687-14.497 14.13-25.368 28.948-19.908z" fill="#EEC170"/><path d="m261.57 319.07c-2.495-14.418 4.6853-22.603 14.596-26.108 9.8945-3.4995 23.181 3.4303 26.267 13.779 4.6504 15.591-7.1651 29.064-21.665 28.161-8.5254-0.53088-17.202-6.5094-19.198-15.831z" fill="#EEC170"/><path d="m336.91 333.41c-9.0175-4.2491-15.337-14.349-13.829-21.682 3.0825-14.989 13.341-20.304 23.018-19.585 10.653 0.79141 17.93 7.407 19.765 17.547 1.9588 10.824-4.1171 19.939-13.494 23.703-5.272 2.1162-10.091 1.5086-15.46 0.017883z" fill="#EEC170"/><text style="fill: rgb(255, 255, 255); font-family: Arial, sans-serif; font-size: 268.3px; font-weight: 700; white-space: pre;" x="531.151" y="358.747">AliasVault</text></svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

Before

Width:  |  Height:  |  Size: 188 KiB

After

Width:  |  Height:  |  Size: 188 KiB

14
docs/contact/index.md Normal file
View File

@@ -0,0 +1,14 @@
---
layout: default
title: Help and Support
has_children: true
nav_order: 100
---
# Help and Support
If you need help or have any questions about installing or using AliasVault, you can reach us on [AliasVault Discord](https://discord.gg/DsaXMTEtpF).
If you have found a bug or have a feature request, please open an issue on [AliasVault GitHub](https://github.com/lanedirt/AliasVault/issues).
If you have any other questions or feedback, please use the contact form on the [AliasVault website](https://aliasvault.net/contact).

12
docs/docker-compose.yml Normal file
View File

@@ -0,0 +1,12 @@
services:
jekyll:
build: .
volumes:
- .:/srv/jekyll
ports:
- "4000:4000"
command: bundle exec jekyll serve --host 0.0.0.0 --watch --force_polling --livereload
environment:
- JEKYLL_ENV=development
- JEKYLL_NO_CACHE=true
- DISABLE_DISK_CACHE=true

45
docs/index.md Normal file
View File

@@ -0,0 +1,45 @@
---
layout: home
title: Home
nav_order: 1
description: "AliasVault Documentation - Open-source password and identity manager"
permalink: /
---
# AliasVault Documentation
{: .fs-9 }
Open-source password and identity manager with email alias generation and zero-knowledge architecture.
{: .fs-6 .fw-300 }
[Installation](./installation){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 }
[View on GitHub](https://github.com/lanedirt/AliasVault){: .btn .fs-5 .mb-4 .mb-md-0 }
---
## What is AliasVault?
AliasVault is a self-hosted password and identity manager that helps you:
- 🔐 **Secure Passwords** - Store and manage passwords with zero-knowledge encryption
- 📧 **Email Aliases** - Generate unique email addresses for each service
- 🎭 **Identity Management** - Create and manage separate online identities
- 🏠 **Self-Hosted** - Run on your own infrastructure using Docker
- 🔓 **Open Source** - Transparent, auditable, and free to use
## Key Features
### Zero-Knowledge Architecture
All data is end-to-end encrypted on the client. Your master password never leaves your device, and the server never has access to your data.
### Built-in Email Server
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.
---
## Getting Started
Ready to get started with AliasVault? Check out the [installation guide](./installation).

View File

@@ -0,0 +1,33 @@
---
layout: default
title: Build from Source
parent: Installation Guide
nav_order: 1
---
# Build from Source
Instead of using the pre-built Docker images, you can also build the images from source yourself. This allows you to build a specific version of AliasVault and/or to make changes to the source code.
Building from source requires more resources:
- Minimum 2GB RAM (more RAM will speed up build time)
- At least 1 vCPU
- 40GB+ disk space (for dependencies and build artifacts)
- Docker installed
- Git installed
## Steps
1. Clone the repository
```bash
git clone https://github.com/lanedirt/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
```
> **Note:** The build process can take a while depending on your hardware (5-15 minutes).
3. After the script completes, you can access AliasVault at:
- Client: `https://localhost`
- Admin: `https://localhost/admin`

View File

@@ -0,0 +1,83 @@
---
layout: default
title: Installation Guide
nav_order: 2
---
# Installation
Follow the steps below to install AliasVault on your own server. Minimum experience with Docker and Linux is required.
{: .toc }
* TOC
{:toc}
---
## 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
- Linux VM with root access (Ubuntu or RHEL based distros recommended)
- 1 vCPU
- 512MB RAM
- 16GB disk space
- Docker installed
### 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
curl -o install.sh https://raw.githubusercontent.com/lanedirt/AliasVault/main/install.sh
```
2. Make the install script executable.
```bash
chmod +x install.sh
```
3. Run the install script. This will create the .env file, pull the Docker images, and start the AliasVault containers. Follow the on-screen prompts to configure AliasVault.
```bash
./install.sh install
```
> **Note**: AliasVault binds to ports 80 and 443 by default. If you want to change the default AliasVault ports you can do so in the `docker-compose.yml` file for the `reverse-proxy` (nginx) container. Afterwards re-run the `./install.sh install` command to restart the containers with the new port settings.
3. After the script completes, you can access AliasVault at:
- Client: `https://localhost`
- Admin: `https://localhost/admin`
---
## 2. SSL configuration
The default installation will create a self-signed SSL certificate and configure Nginx to use it.
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:
- A public IPv4 address assigned to your server
- Port 80 and 443 on your server must be open and accessible from the internet
- A registered domain name with an A record pointing to your server's public IP address (e.g. mydomain.com)
### Steps
1. Run the install script with the `configure-ssl` option
```bash
./install.sh configure-ssl
```
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
and then in the prompt choose option 2.
---
## 3. Troubleshooting
### Resetting the admin password
If you have lost your admin password, you can reset it by running the install script with the `reset-password` option. This will generate a new random password and update the .env file with it. After that it will restart the AliasVault containers to apply the changes.
```bash
./install.sh reset-password
```
### Verbose output
If you need more detailed output from the install script, you can run it with the `--verbose` option. This will print more information to the console.
```bash
./install.sh install --verbose
```

View File

@@ -1,6 +1,13 @@
# Manual Setup Instructions for AliasVault
---
layout: default
title: Manual Setup
parent: Installation Guide
nav_order: 2
---
This README provides step-by-step instructions for manually setting up AliasVault without using the `install.sh` script. Follow these steps if you prefer to execute all statements yourself.
# Manual Setup
If you prefer to manually set up AliasVault, this README provides step-by-step instructions. Follow these steps if you prefer to execute all statements yourself.
## Prerequisites

View File

@@ -0,0 +1,30 @@
---
layout: default
title: Start/stop
parent: Installation Guide
nav_order: 3
---
# Starting and stopping AliasVault
You can start and stop 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
```
## Start
To start AliasVault, run the install script with the `start` option. This will start all AliasVault containers.
```bash
./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
```

View File

@@ -0,0 +1,19 @@
---
layout: default
title: Uninstall
parent: Installation Guide
nav_order: 5
---
# 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.
{: .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 the install script with the `uninstall` option
```bash
./install.sh uninstall
```

View File

@@ -0,0 +1,32 @@
---
layout: default
title: Update
parent: Installation Guide
nav_order: 4
---
# Updating AliasVault
To update AliasVault to the latest version, run the install script with the `update` option. This will pull the latest version of AliasVault from GitHub and restart all containers.
You can see the latest available version of AliasVault on [GitHub](https://github.com/lanedirt/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.
## Updating to the latest available version
To update to the latest version, run the install script with the `update` option. The script will check for the latest version and prompt you to confirm the update. Follow the prompts to complete the update.
```bash
./install.sh update
```
## Installing a specific version
To install a specific version and skip the automatic version checks, run the install script with the `install` option and specify the version you want to install.
```bash
./install.sh install <version>
# Example:
./install.sh install 0.7.0
```

View File

@@ -1,3 +1,12 @@
---
layout: default
title: Configure SQLite for use with WebAssembly
parent: Development
grand_parent: Miscellaneous
nav_order: 2
---
# Configure SQLite for use with WebAssembly
To configure SQLite for use with WebAssembly follow these steps:
1. Add NuGet package

View File

@@ -1,3 +1,12 @@
---
layout: default
title: Enable WebAuthn
parent: Development
grand_parent: Miscellaneous
nav_order: 1
---
# WebAuthn
The webauthn implementation in order to quick unlock the vault requires the use of a FIDO2 authenticator.
This can be either the built-in browser authenticator or an external authenticator like a Yubikey.

6
docs/misc/dev/index.md Normal file
View File

@@ -0,0 +1,6 @@
---
layout: default
title: Development
parent: Miscellaneous
nav_order: 1
---

View File

@@ -1,3 +1,11 @@
---
layout: default
title: 1. Run GitHub Actions Locally
parent: Development
grand_parent: Miscellaneous
nav_order: 1
---
# Run GitHub Actions Locally
This guide will help you set up and run GitHub Actions locally on Linux, which can be useful for debugging and testing your workflows without pushing changes to the repository.

View File

@@ -1,3 +1,13 @@
---
layout: default
title: Upgrade the AliasClientDb EF model
parent: Development
grand_parent: Miscellaneous
nav_order: 3
---
# Upgrade the AliasClientDb EF model
To upgrade the AliasClientDb EF model, follow these steps:
1. Make changes to the AliasClientDb EF model in the `AliasClientDb` project.

10
docs/misc/index.md Normal file
View File

@@ -0,0 +1,10 @@
---
layout: default
title: Miscellaneous
has_children: true
nav_order: 99
---
# Miscellaneous
Miscellaneous guides and documentation.

View File

@@ -37,11 +37,15 @@ show_usage() {
printf "Usage: $0 [COMMAND] [OPTIONS]\n"
printf "\n"
printf "Commands:\n"
printf " install Install AliasVault by pulling pre-built images from GitHub Container Registry (default)\n"
printf " build Build AliasVault from source (takes longer and requires sufficient specs)\n"
printf " reset-password Reset admin password\n"
printf " install Install AliasVault by pulling pre-built images from GitHub Container Registry (recommended)\n"
printf " uninstall Uninstall AliasVault\n"
printf " update Update AliasVault to the latest version\n"
printf " configure-ssl Configure SSL certificates (Let's Encrypt or self-signed)\n"
printf " start Start AliasVault containers\n"
printf " stop Stop AliasVault containers\n"
printf " restart Restart AliasVault containers\n"
printf " reset-password Reset admin password\n"
printf " build Build AliasVault from source (takes longer and requires sufficient specs)\n"
printf "\n"
printf "Options:\n"
@@ -52,38 +56,74 @@ show_usage() {
# Function to parse command line arguments
parse_args() {
COMMAND="" # Remove default command
COMMAND=""
VERBOSE=false
FORCE_YES=false
COMMAND_ARG=""
# Show usage if no arguments provided
if [ $# -eq 0 ]; then
show_usage
exit 0
fi
# First argument is always the command
case $1 in
install|i)
COMMAND="install"
shift
# Check for version argument
if [ $# -gt 0 ] && [[ ! "$1" =~ ^- ]]; then
COMMAND_ARG="$1"
shift
fi
;;
# Other commands remain unchanged
build|b)
COMMAND="build"
shift
;;
uninstall|u)
COMMAND="uninstall"
shift
;;
reset-password|reset-admin-password|rp)
COMMAND="reset-password"
shift
;;
configure-ssl|ssl)
COMMAND="configure-ssl"
shift
;;
start|s)
COMMAND="start"
shift
;;
stop|st)
COMMAND="stop"
shift
;;
restart|r)
COMMAND="restart"
shift
;;
update|up)
COMMAND="update"
shift
;;
--help)
show_usage
exit 0
;;
*)
echo "Unknown option: $1"
show_usage
exit 1
;;
esac
# Parse remaining flags
while [[ $# -gt 0 ]]; do
case $1 in
install|i)
COMMAND="install"
shift
;;
build|b)
COMMAND="build"
shift
;;
uninstall|u)
COMMAND="uninstall"
shift
;;
reset-password|reset-admin-password|rp)
COMMAND="reset-password"
shift
;;
configure-ssl|ssl)
COMMAND="configure-ssl"
shift
;;
--verbose)
VERBOSE=true
shift
@@ -92,10 +132,6 @@ parse_args() {
FORCE_YES=true
shift
;;
--help)
show_usage
exit 0
;;
*)
echo "Unknown option: $1"
show_usage
@@ -118,7 +154,7 @@ main() {
print_logo
case $COMMAND in
"install")
handle_install
handle_install "$COMMAND_ARG"
;;
"build")
handle_build
@@ -136,6 +172,18 @@ main() {
"configure-ssl")
handle_ssl_configuration
;;
"start")
handle_start
;;
"stop")
handle_stop
;;
"restart")
handle_restart
;;
"update")
handle_update
;;
esac
}
@@ -173,21 +221,35 @@ initialize_workspace() {
# Function to handle docker-compose.yml
handle_docker_compose() {
printf "${CYAN}> Checking docker-compose.yml...${NC}\n"
printf "${CYAN}> Checking docker-compose files...${NC}\n"
if [ -f "docker-compose.yml" ]; then
printf " ${GREEN}> docker-compose.yml already exists.${NC}\n"
return 0
fi
printf " ${CYAN}> Downloading docker-compose.yml...${NC}"
if curl -sSf "${GITHUB_RAW_URL}/docker-compose.yml" -o "docker-compose.yml" > /dev/null 2>&1; then
printf "\n ${GREEN}> docker-compose.yml downloaded successfully.${NC}\n"
return 0
# Check and download main docker-compose.yml
if [ ! -f "docker-compose.yml" ]; then
printf " ${CYAN}> Downloading docker-compose.yml...${NC}"
if curl -sSf "${GITHUB_RAW_URL}/docker-compose.yml" -o "docker-compose.yml" > /dev/null 2>&1; then
printf "\n ${GREEN}> docker-compose.yml downloaded successfully.${NC}\n"
else
printf "\n ${YELLOW}> Failed to download docker-compose.yml, please check your internet connection and try again. Alternatively, you can download it manually from https://github.com/${REPO_OWNER}/${REPO_NAME}/blob/main/docker-compose.yml and place it in the root directory of AliasVault.${NC}\n"
exit 1
fi
else
printf "\n ${YELLOW}> Failed to download docker-compose.yml, please check your internet connection and try again. Alternatively, you can download it manually from https://github.com/${REPO_OWNER}/${REPO_NAME}/blob/main/docker-compose.yml and place it in the root directory of AliasVault.${NC}\n"
exit 1
printf " ${GREEN}> docker-compose.yml already exists.${NC}\n"
fi
# Check and download docker-compose.letsencrypt.yml
if [ ! -f "docker-compose.letsencrypt.yml" ]; then
printf " ${CYAN}> Downloading docker-compose.letsencrypt.yml...${NC}"
if curl -sSf "${GITHUB_RAW_URL}/docker-compose.letsencrypt.yml" -o "docker-compose.letsencrypt.yml" > /dev/null 2>&1; then
printf "\n ${GREEN}> docker-compose.letsencrypt.yml downloaded successfully.${NC}\n"
else
printf "\n ${YELLOW}> Failed to download docker-compose.letsencrypt.yml, please check your internet connection and try again. Alternatively, you can download it manually from https://github.com/${REPO_OWNER}/${REPO_NAME}/blob/main/docker-compose.letsencrypt.yml and place it in the root directory of AliasVault.${NC}\n"
exit 1
fi
else
printf " ${GREEN}> docker-compose.letsencrypt.yml already exists.${NC}\n"
fi
return 0
}
# Function to print the logo
@@ -351,6 +413,16 @@ update_env_var() {
printf " ${GREEN}> $key has been set in $ENV_FILE.${NC}\n"
}
# Helper function to delete environment variables
delete_env_var() {
local key=$1
if [ -f "$ENV_FILE" ]; then
sed -i.bak "/^${key}=/d" "$ENV_FILE" && rm -f "$ENV_FILE.bak"
printf " ${GREEN}> $key has been removed from $ENV_FILE.${NC}\n"
fi
}
# Function to print success message
print_success_message() {
printf "\n"
@@ -420,60 +492,38 @@ get_docker_compose_command() {
echo "$base_command"
}
# Function to handle installation
# Function to handle initial installation or reinstallation
handle_install() {
printf "${YELLOW}+++ Installing AliasVault +++${NC}\n"
printf "\n"
local specified_version="$1"
# Initialize workspace which makes sure all required directories and files exist
initialize_workspace
# Initialize environment
create_env_file || { printf "${RED}> Failed to create .env file${NC}\n"; exit 1; }
populate_hostname || { printf "${RED}> Failed to set hostname${NC}\n"; exit 1; }
populate_jwt_key || { printf "${RED}> Failed to set JWT key${NC}\n"; exit 1; }
populate_data_protection_cert_pass || { printf "${RED}> Failed to set certificate password${NC}\n"; exit 1; }
set_private_email_domains || { printf "${RED}> Failed to set email domains${NC}\n"; exit 1; }
set_smtp_tls_enabled || { printf "${RED}> Failed to set SMTP TLS${NC}\n"; exit 1; }
set_support_email || { printf "${RED}> Failed to set support email${NC}\n"; exit 1; }
# Only generate admin password if not already set
if ! grep -q "^ADMIN_PASSWORD_HASH=" "$ENV_FILE" || [ -z "$(grep "^ADMIN_PASSWORD_HASH=" "$ENV_FILE" | cut -d '=' -f2)" ]; then
generate_admin_password || { printf "${RED}> Failed to generate admin password${NC}\n"; exit 1; }
# If version specified, install that version directly
if [ -n "$specified_version" ]; then
handle_install_version "$specified_version"
return
fi
# Pull images from GitHub Container Registry
printf "\n${YELLOW}+++ Pulling Docker images +++${NC}\n"
printf "\n"
# Check for existing version
local current_version=""
if grep -q "^ALIASVAULT_VERSION=" "$ENV_FILE"; then
current_version=$(grep "^ALIASVAULT_VERSION=" "$ENV_FILE" | cut -d '=' -f2)
printf "${CYAN}> Current AliasVault version: ${current_version}${NC}\n"
printf "${YELLOW}> AliasVault is already installed.${NC}\n"
printf "1. To reinstall the current version (${current_version}), continue with this script\n"
printf "2. To check for updates and to install the latest version, use: ./install.sh update\n"
printf "3. To install a specific version, use: ./install.sh install <version>\n"
printf "\n"
images=(
"${GITHUB_CONTAINER_REGISTRY}-reverse-proxy:latest"
"${GITHUB_CONTAINER_REGISTRY}-api:latest"
"${GITHUB_CONTAINER_REGISTRY}-client:latest"
"${GITHUB_CONTAINER_REGISTRY}-admin:latest"
"${GITHUB_CONTAINER_REGISTRY}-smtp:latest"
)
for image in "${images[@]}"; do
printf "${CYAN}> Pulling $image...${NC}\n"
if [ "$VERBOSE" = true ]; then
docker pull $image || { printf "${RED}> Failed to pull image: $image${NC}\n"; exit 1; }
else
docker pull $image > /dev/null 2>&1 || { printf "${RED}> Failed to pull image: $image${NC}\n"; exit 1; }
read -p "Would you like to reinstall the current version? [y/N]: " REPLY
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
printf "${YELLOW}> Installation cancelled.${NC}\n"
exit 0
fi
done
# Start containers
printf "\n${YELLOW}+++ Starting services +++${NC}\n"
printf "\n"
if [ "$VERBOSE" = true ]; then
$(get_docker_compose_command) up -d || { printf "${RED}> Failed to start Docker containers${NC}\n"; exit 1; }
handle_install_version "$current_version"
else
$(get_docker_compose_command) up -d > /dev/null 2>&1 || { printf "${RED}> Failed to start Docker containers${NC}\n"; exit 1; }
# First time installation, use latest
handle_install_version "latest"
fi
# Only show success message if we made it here without errors
print_success_message
}
# Function to handle build
@@ -539,12 +589,12 @@ handle_build() {
printf "${CYAN}> Starting Docker Compose stack...${NC}\n"
if [ "$VERBOSE" = true ]; then
$(get_docker_compose_command "build") up -d || {
$(get_docker_compose_command "build") up -d --force-recreate || {
printf "${RED}> Failed to start Docker Compose stack${NC}\n"
exit 1
}
else
$(get_docker_compose_command "build") up -d > /dev/null 2>&1 || {
$(get_docker_compose_command "build") up -d --force-recreate > /dev/null 2>&1 || {
printf "${RED}> Failed to start Docker Compose stack${NC}\n"
exit 1
}
@@ -584,6 +634,9 @@ handle_uninstall() {
fi
printf "${GREEN}> Docker containers stopped and removed.${NC}\n"
# Remove version from .env
delete_env_var "ALIASVAULT_VERSION" ""
printf "${CYAN}> Removing Docker images...${NC}\n"
if [ "$VERBOSE" = true ]; then
docker compose -f docker-compose.yml down --rmi all || {
@@ -746,7 +799,6 @@ configure_letsencrypt() {
# Request certificate using a temporary certbot container
printf "${CYAN}> Requesting Let's Encrypt certificate...${NC}\n"
docker run --rm \
--network aliasvault_default \
-v ./certificates/letsencrypt:/etc/letsencrypt:rw \
-v ./certificates/letsencrypt/www:/var/www/certbot:rw \
certbot/certbot certonly \
@@ -776,7 +828,7 @@ 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
$(get_docker_compose_command) up -d reverse-proxy --force-recreate
printf "${GREEN}> Let's Encrypt SSL certificate has been configured successfully!${NC}\n"
}
@@ -805,4 +857,149 @@ generate_self_signed_cert() {
printf "${GREEN}> New self-signed certificate has been generated successfully!${NC}\n"
}
# New functions to handle container lifecycle:
handle_start() {
printf "${CYAN}> Starting AliasVault containers...${NC}\n"
$(get_docker_compose_command) up -d
printf "${GREEN}> AliasVault containers started successfully.${NC}\n"
}
handle_stop() {
printf "${CYAN}> Stopping AliasVault containers...${NC}\n"
if ! docker compose ps --quiet 2>/dev/null | grep -q .; then
printf "${YELLOW}> No containers are currently running.${NC}\n"
exit 0
fi
$(get_docker_compose_command) down
printf "${GREEN}> AliasVault containers stopped successfully.${NC}\n"
}
handle_restart() {
printf "${CYAN}> Restarting AliasVault containers...${NC}\n"
$(get_docker_compose_command) down
$(get_docker_compose_command) up -d
printf "${GREEN}> AliasVault containers restarted successfully.${NC}\n"
}
# Function to handle updates
handle_update() {
printf "${YELLOW}+++ Checking for AliasVault updates +++${NC}\n"
printf "\n"
# Check current version
if ! grep -q "^ALIASVAULT_VERSION=" "$ENV_FILE"; then
printf "${YELLOW}> No version information found. Running first-time update check...${NC}\n"
handle_install_version "latest"
return
fi
current_version=$(grep "^ALIASVAULT_VERSION=" "$ENV_FILE" | cut -d '=' -f2)
latest_version=$(curl -s "https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
if [ -z "$latest_version" ]; then
printf "${RED}> Failed to check for updates. Please try again later.${NC}\n"
exit 1
fi
printf "${CYAN}> Current version: ${current_version}${NC}\n"
printf "${CYAN}> Latest version: ${latest_version}${NC}\n"
printf "\n"
if [ "$current_version" = "$latest_version" ]; then
printf "${GREEN}> You are already running the latest version of AliasVault!${NC}\n"
exit 0
fi
printf "${YELLOW}> A new version of AliasVault is available!${NC}\n"
printf "\n"
printf "${MAGENTA}Important:${NC}\n"
printf "1. It's recommended to backup your database before updating\n"
printf "2. The update process will restart all containers\n"
printf "\n"
read -p "Would you like to update to the latest version? [y/N]: " REPLY
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
printf "${YELLOW}> Update cancelled.${NC}\n"
exit 0
fi
printf "${CYAN}> Updating AliasVault...${NC}\n"
handle_install_version "$latest_version"
printf "${GREEN}> Update completed successfully!${NC}\n"
}
# Function to perform the actual installation with specific version
handle_install_version() {
local target_version="$1"
# If latest, get actual version number from GitHub API
if [ "$target_version" = "latest" ]; then
local actual_version=$(curl -s "https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
if [ -n "$actual_version" ]; then
target_version="$actual_version"
fi
fi
printf "${YELLOW}+++ Installing AliasVault ${target_version} +++${NC}\n"
printf "\n"
# Initialize workspace which makes sure all required directories and files exist
initialize_workspace
# Initialize environment
create_env_file || { printf "${RED}> Failed to create .env file${NC}\n"; exit 1; }
populate_hostname || { printf "${RED}> Failed to set hostname${NC}\n"; exit 1; }
populate_jwt_key || { printf "${RED}> Failed to set JWT key${NC}\n"; exit 1; }
populate_data_protection_cert_pass || { printf "${RED}> Failed to set certificate password${NC}\n"; exit 1; }
set_private_email_domains || { printf "${RED}> Failed to set email domains${NC}\n"; exit 1; }
set_smtp_tls_enabled || { printf "${RED}> Failed to set SMTP TLS${NC}\n"; exit 1; }
set_support_email || { printf "${RED}> Failed to set support email${NC}\n"; exit 1; }
# Only generate admin password if not already set
if ! grep -q "^ADMIN_PASSWORD_HASH=" "$ENV_FILE" || [ -z "$(grep "^ADMIN_PASSWORD_HASH=" "$ENV_FILE" | cut -d '=' -f2)" ]; then
generate_admin_password || { printf "${RED}> Failed to generate admin password${NC}\n"; exit 1; }
fi
# Pull images from GitHub Container Registry
printf "\n${YELLOW}+++ Pulling Docker images +++${NC}\n"
printf "\n"
printf "${CYAN}> Installing version: ${target_version}${NC}\n"
local tag="$target_version"
if [ "$target_version" = "latest" ]; then
tag="latest"
fi
images=(
"${GITHUB_CONTAINER_REGISTRY}-reverse-proxy:${tag}"
"${GITHUB_CONTAINER_REGISTRY}-api:${tag}"
"${GITHUB_CONTAINER_REGISTRY}-client:${tag}"
"${GITHUB_CONTAINER_REGISTRY}-admin:${tag}"
"${GITHUB_CONTAINER_REGISTRY}-smtp:${tag}"
)
for image in "${images[@]}"; do
printf "${CYAN}> Pulling $image...${NC}\n"
if [ "$VERBOSE" = true ]; then
docker pull $image || { printf "${RED}> Failed to pull image: $image${NC}\n"; exit 1; }
else
docker pull $image > /dev/null 2>&1 || { printf "${RED}> Failed to pull image: $image${NC}\n"; exit 1; }
fi
done
# Save version to .env
update_env_var "ALIASVAULT_VERSION" "$target_version"
# Start containers
printf "\n${YELLOW}+++ Starting services +++${NC}\n"
printf "\n"
recreate_docker_containers
# Only show success message if we made it here without errors
print_success_message
}
main "$@"

View File

@@ -4,22 +4,17 @@ EXPOSE 3002
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["src/AliasVault.Admin/AliasVault.Admin.csproj", "src/AliasVault.Admin/"]
RUN dotnet restore "src/AliasVault.Admin/AliasVault.Admin.csproj"
COPY . .
WORKDIR "/src/src/AliasVault.Admin"
RUN dotnet build "AliasVault.Admin.csproj" -c "$BUILD_CONFIGURATION" -o /app/build
FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "AliasVault.Admin.csproj" -c "$BUILD_CONFIGURATION" -o /app/publish /p:UseAppHost=false
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
COPY --from=build /app/publish .
ENV ASPNETCORE_URLS=http://+:3002
ENV ASPNETCORE_PATHBASE=/admin

View File

@@ -37,6 +37,8 @@ config.LastPasswordChanged = DateTime.Parse(lastPasswordChanged, CultureInfo.Inv
builder.Services.AddSingleton(config);
builder.Services.AddAliasVaultDataProtection("AliasVault.Api");
// Add services to the container.
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents();
@@ -85,7 +87,6 @@ builder.Services.AddIdentityCore<AdminUser>(options =>
.AddSignInManager()
.AddDefaultTokenProviders();
builder.Services.AddAliasVaultDataProtection("AliasVault.Admin");
builder.Services.Configure<DataProtectionTokenProviderOptions>(options =>
{
options.TokenLifespan = TimeSpan.FromDays(30);

View File

@@ -23,7 +23,7 @@
<PackageReference Include="Asp.Versioning.Mvc" Version="8.1.0" />
<PackageReference Include="Asp.Versioning.Mvc.ApiExplorer" Version="8.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.0" />
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.2.0" />
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.2.1" />
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="8.2.1" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.556">
<PrivateAssets>all</PrivateAssets>

View File

@@ -137,8 +137,6 @@ public class AuthController(IDbContextFactory<AliasServerDbContext> dbContextFac
return Ok(new ValidateLoginResponse(true, string.Empty, null));
}
// If 2FA is not required, then it means the user is successfully authenticated at this point.
// Reset failed login attempts.
await userManager.ResetAccessFailedCountAsync(user);
@@ -246,6 +244,12 @@ public class AuthController(IDbContextFactory<AliasServerDbContext> dbContextFac
{
await using var context = await dbContextFactory.CreateDbContextAsync();
// If the token is not provided, return bad request.
if (string.IsNullOrWhiteSpace(tokenModel.RefreshToken))
{
return BadRequest("Refresh token is required.");
}
var principal = GetPrincipalFromToken(tokenModel.Token);
if (principal.FindFirst(ClaimTypes.NameIdentifier)?.Value == null)
{
@@ -284,6 +288,12 @@ public class AuthController(IDbContextFactory<AliasServerDbContext> dbContextFac
{
await using var context = await dbContextFactory.CreateDbContextAsync();
// If the token is not provided, return bad request.
if (string.IsNullOrWhiteSpace(model.RefreshToken))
{
return BadRequest("Refresh token is required.");
}
var principal = GetPrincipalFromToken(model.Token);
if (principal.FindFirst(ClaimTypes.NameIdentifier)?.Value == null)
{
@@ -297,16 +307,18 @@ public class AuthController(IDbContextFactory<AliasServerDbContext> dbContextFac
}
// Check if the refresh token is valid.
var deviceIdentifier = GenerateDeviceIdentifier(Request);
var existingToken = await context.AliasVaultUserRefreshTokens.FirstOrDefaultAsync(t => t.UserId == user.Id && t.DeviceIdentifier == deviceIdentifier);
if (existingToken == null || existingToken.Value != model.RefreshToken)
var providedTokenExists = await context.AliasVaultUserRefreshTokens.AnyAsync(t => t.UserId == user.Id && t.Value == model.RefreshToken);
if (!providedTokenExists)
{
await authLoggingService.LogAuthEventFailAsync(user.UserName!, AuthEventType.Logout, AuthFailureReason.InvalidRefreshToken);
return Unauthorized("Invalid refresh token");
}
// Remove the existing refresh token.
context.AliasVaultUserRefreshTokens.Remove(existingToken);
// Remove the provided refresh token and any other existing refresh tokens that are issued to the current device ID.
// This to make sure all tokens are revoked for this device that user is "logging out" from.
var deviceIdentifier = GenerateDeviceIdentifier(Request);
var allDeviceTokens = await context.AliasVaultUserRefreshTokens.Where(t => t.UserId == user.Id && (t.Value == model.RefreshToken || t.DeviceIdentifier == deviceIdentifier)).ToListAsync();
context.AliasVaultUserRefreshTokens.RemoveRange(allDeviceTokens);
await context.SaveChangesAsync();
await authLoggingService.LogAuthEventSuccessAsync(user.UserName!, AuthEventType.Logout);
@@ -705,8 +717,14 @@ public class AuthController(IDbContextFactory<AliasServerDbContext> dbContextFac
// New refresh token lifetime is the same as the existing one.
var existingTokenLifetime = existingToken.ExpireDate - existingToken.CreatedAt;
// Retrieve new refresh token.
var newRefreshToken = await GenerateRefreshToken(user, existingTokenLifetime, existingToken.Value);
// After successfully retrieving new refresh token, remove the existing one by saving changes.
await context.SaveChangesAsync();
// Return new refresh token.
return await GenerateRefreshToken(user, existingTokenLifetime, existingToken.Value);
return newRefreshToken;
}
finally
{

View File

@@ -48,6 +48,7 @@ public class SecurityController(IDbContextFactory<AliasServerDbContext> dbContex
ExpireDate = x.ExpireDate,
CreatedAt = x.CreatedAt,
})
.Where(x => x.ExpireDate > DateTime.UtcNow)
.OrderByDescending(x => x.CreatedAt)
.ToListAsync();

View File

@@ -11,15 +11,11 @@ RUN dotnet restore "src/AliasVault.Api/AliasVault.Api.csproj"
COPY . .
WORKDIR "/src/src/AliasVault.Api"
RUN dotnet build "AliasVault.Api.csproj" -c "$BUILD_CONFIGURATION" -o /app/build
FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "AliasVault.Api.csproj" -c "$BUILD_CONFIGURATION" -o /app/publish /p:UseAppHost=false
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
COPY --from=build /app/publish .
ENV ASPNETCORE_URLS=http://+:3001
ENV ASPNETCORE_PATHBASE=/api

View File

@@ -26,6 +26,7 @@ builder.Configuration.AddJsonFile("appsettings.json", optional: false, reloadOnC
builder.Configuration.AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true, reloadOnChange: true);
builder.Services.ConfigureLogging(builder.Configuration, Assembly.GetExecutingAssembly().GetName().Name!, "../../logs");
builder.Services.AddAliasVaultDataProtection("AliasVault.Api");
builder.Services.AddSingleton<ITimeProvider, SystemTimeProvider>();
builder.Services.AddScoped<TimeValidationJwtBearerEvents>();
builder.Services.AddScoped<AuthLoggingService>();
@@ -40,8 +41,6 @@ builder.Services.AddLogging(logging =>
});
builder.Services.AddAliasVaultSqliteConfiguration();
builder.Services.AddAliasVaultDataProtection("AliasVault.Api");
builder.Services.AddIdentity<AliasVaultUser, AliasVaultRole>(options =>
{
options.Password.RequireDigit = false;

View File

@@ -10,7 +10,7 @@
<div class="flex-grow p-6 pt-4 lg:pt-6 pb-28 lg:pb-4">
<div class="flex justify-between items-center mb-4">
<div>
<button @onclick="GoBack" class="text-gray-500 hover:text-gray-800 dark:text-gray-400 dark:hover:text-gray-200">
<button @onclick="GoBack" class="text-gray-500 hover:text-gray-800 dark:text-gray-400 dark:hover:text-gray-200 @(_currentStep == SetupStep.TermsAndConditions ? "invisible" : "")">
<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"></path>
</svg>

View File

@@ -18,19 +18,14 @@ COPY ["src/AliasVault.Client/AliasVault.Client.csproj", "src/AliasVault.Client/"
RUN dotnet restore "src/AliasVault.Client/AliasVault.Client.csproj"
COPY . .
# Build the Client project
# Build and publish
WORKDIR "/src/src/AliasVault.Client"
RUN dotnet build "AliasVault.Client.csproj" -c "$BUILD_CONFIGURATION" -o /app/build
# Publish the Client project
FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "AliasVault.Client.csproj" -c "$BUILD_CONFIGURATION" -o /app/publish /p:UseAppHost=false
# Final stage
FROM nginx:1.24.0 AS final
WORKDIR /usr/share/nginx/html
COPY --from=publish /app/publish/wwwroot .
COPY --from=build /app/publish/wwwroot .
COPY /src/AliasVault.Client/nginx.conf /etc/nginx/nginx.conf
COPY /src/AliasVault.Client/entrypoint.sh /app/entrypoint.sh

View File

@@ -8,7 +8,7 @@
<ConfirmModal />
<FullScreenLoadingIndicator @ref="LoadingIndicator" />
<TopMenu />
<div class="flex pt-16 pb-4 lg:pb-16 overflow-hidden bg-gray-100 dark:bg-gray-900">
<div class="flex pt-16 mb-4 lg:mb-16 overflow-hidden bg-gray-100 dark:bg-gray-900 relative z-20">
<div id="main-content" class="relative z-10 w-full max-w-screen-2xl mx-auto h-full overflow-y-auto bg-gray-100 dark:bg-gray-900">
<main>
<GlobalNotificationDisplay />

View File

@@ -85,7 +85,7 @@
/// </summary>
public async Task DisableWebAuthn()
{
await AuthService.SetWebAuthnEnabledAsync(false, string.Empty, string.Empty, string.Empty);
await AuthService.SetWebAuthnEnabledAsync(false);
GlobalNotificationService.AddSuccessMessage("Quick Vault Unlock is successfully disabled.", true);
await LoadData();
}

View File

@@ -194,7 +194,7 @@ public sealed class AuthService(HttpClient httpClient, ILocalStorageService loca
/// <param name="webauthSalt">WebAuthn salt.</param>
/// <param name="webauthCredentialDerivedKey">WebAuthn credential derived key.</param>
/// <returns>Task.</returns>
public async Task SetWebAuthnEnabledAsync(bool enabled, string? webauthCredentialId, string? webauthSalt, string? webauthCredentialDerivedKey)
public async Task SetWebAuthnEnabledAsync(bool enabled, string? webauthCredentialId = null, string? webauthSalt = null, string? webauthCredentialDerivedKey = null)
{
await localStorage.SetItemAsStringAsync("webAuthnEnabled", enabled.ToString().ToLower());
@@ -311,7 +311,7 @@ public sealed class AuthService(HttpClient httpClient, ILocalStorageService loca
private async Task RevokeTokenAsync()
{
// Remove webauthn enabled flag.
await SetWebAuthnEnabledAsync(false, null, null, null);
await SetWebAuthnEnabledAsync(false);
var tokenInput = new TokenModel
{

View File

@@ -1,10 +1,8 @@
#blazor-error-ui {
background: lightyellow;
bottom: 0;
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
display: none;
left: 0;
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
position: fixed;
width: 100%;
z-index: 1000;
@@ -18,7 +16,6 @@
}
.blazor-error-boundary {
background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
padding: 1rem 1rem 1rem 3.7rem;
color: white;
}

View File

@@ -690,6 +690,10 @@ video {
z-index: 50;
}
.z-20 {
z-index: 20;
}
.col-span-1 {
grid-column: span 1 / span 1;
}
@@ -1024,6 +1028,10 @@ video {
max-width: 36rem;
}
.max-w-screen-xl {
max-width: 1280px;
}
.flex-shrink-0 {
flex-shrink: 0;
}
@@ -1350,6 +1358,11 @@ video {
border-color: rgb(214 131 56 / var(--tw-border-opacity));
}
.border-red-500 {
--tw-border-opacity: 1;
border-color: rgb(239 68 68 / var(--tw-border-opacity));
}
.bg-amber-50 {
--tw-bg-opacity: 1;
background-color: rgb(255 251 235 / var(--tw-bg-opacity));
@@ -1895,6 +1908,11 @@ video {
color: rgb(133 77 14 / var(--tw-text-opacity));
}
.text-amber-500 {
--tw-text-opacity: 1;
color: rgb(245 158 11 / var(--tw-text-opacity));
}
.opacity-0 {
opacity: 0;
}
@@ -2070,6 +2088,11 @@ video {
background-color: rgb(153 27 27 / var(--tw-bg-opacity));
}
.hover\:bg-red-700:hover {
--tw-bg-opacity: 1;
background-color: rgb(185 28 28 / var(--tw-bg-opacity));
}
.hover\:from-primary-600:hover {
--tw-gradient-from: #d68338 var(--tw-gradient-from-position);
--tw-gradient-to: rgb(214 131 56 / 0) var(--tw-gradient-to-position);
@@ -2125,6 +2148,11 @@ video {
color: rgb(255 255 255 / var(--tw-text-opacity));
}
.hover\:text-red-200:hover {
--tw-text-opacity: 1;
color: rgb(254 202 202 / var(--tw-text-opacity));
}
.hover\:underline:hover {
text-decoration-line: underline;
}
@@ -2280,6 +2308,11 @@ video {
border-color: rgb(234 179 8 / var(--tw-border-opacity));
}
.dark\:border-red-800:is(.dark *) {
--tw-border-opacity: 1;
border-color: rgb(153 27 27 / var(--tw-border-opacity));
}
.dark\:bg-blue-800:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(30 64 175 / var(--tw-bg-opacity));
@@ -2360,6 +2393,11 @@ video {
background-color: rgb(113 63 18 / var(--tw-bg-opacity));
}
.dark\:bg-red-900:is(.dark *) {
--tw-bg-opacity: 1;
background-color: rgb(127 29 29 / var(--tw-bg-opacity));
}
.dark\:bg-opacity-80:is(.dark *) {
--tw-bg-opacity: 0.8;
}
@@ -2638,6 +2676,10 @@ video {
width: auto;
}
.sm\:flex-row {
flex-direction: row;
}
.sm\:rounded-lg {
border-radius: 0.5rem;
}
@@ -2764,6 +2806,10 @@ video {
margin-top: 4rem;
}
.lg\:mb-16 {
margin-bottom: 4rem;
}
.lg\:block {
display: block;
}

View File

@@ -70,10 +70,30 @@
<div id="app">
</div>
<div id="blazor-error-ui">
An unhandled error has occurred.
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
<div id="blazor-error-ui" class="text-white bg-red-700 dark:bg-red-900 p-6 border-t-2 border-red-500 dark:border-red-800">
<div class="container mx-auto max-w-screen-xl px-4">
<div class="flex flex-col sm:flex-row items-center justify-between gap-4">
<div class="flex items-center">
<svg class="w-8 h-8 text-white mr-4 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/>
</svg>
<span>An unhandled error has occurred. Please try reloading the page. If the issue persists, please contact support.</span>
</div>
<div class="flex items-center gap-4">
<a href="" class="reload flex items-center px-4 py-2 bg-red-600 hover:bg-red-700 rounded-md transition-colors duration-150">
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"/>
</svg>
Reload Page
</a>
<a class="dismiss hover:text-red-200">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
</svg>
</a>
</div>
</div>
</div>
</div>
<script>

View File

@@ -237,7 +237,6 @@ public class AliasServerDbContext : WorkerStatusDbContext, IDataProtectionKeyCon
/// <param name="optionsBuilder">DbContextOptionsBuilder instance.</param>
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
// If the options are not already configured, use the appsettings.json file.
if (!optionsBuilder.IsConfigured)
{
var configuration = new ConfigurationBuilder()
@@ -245,11 +244,14 @@ public class AliasServerDbContext : WorkerStatusDbContext, IDataProtectionKeyCon
.AddJsonFile("appsettings.json")
.Build();
// Add SQLite connection with enhanced settings
optionsBuilder
.UseSqlite(configuration.GetConnectionString("AliasServerDbContext"))
.UseSqlite(
configuration.GetConnectionString("AliasServerDbContext") + ";Mode=ReadWriteCreate;Cache=Shared",
options => options.CommandTimeout(60))
.UseLazyLoadingProxies();
// Set busy timeout using PRAGMA to avoid "The database file is locked" error.
// Set additional PRAGMA settings
var connection = Database.GetDbConnection();
if (connection.State != System.Data.ConnectionState.Open)
{
@@ -258,7 +260,13 @@ public class AliasServerDbContext : WorkerStatusDbContext, IDataProtectionKeyCon
using (var command = connection.CreateCommand())
{
command.CommandText = "PRAGMA busy_timeout = 5000;";
// Increase busy timeout
command.CommandText = @"
PRAGMA busy_timeout = 30000;
PRAGMA journal_mode = WAL;
PRAGMA synchronous = FULL;
PRAGMA temp_store = MEMORY;
PRAGMA mmap_size = 1073741824;";
command.ExecuteNonQuery();
}
}

View File

@@ -10,16 +10,11 @@ COPY ["src/Services/AliasVault.SmtpService/AliasVault.SmtpService.csproj", "src/
RUN dotnet restore "./src/Services/AliasVault.SmtpService/AliasVault.SmtpService.csproj"
COPY . .
# Build the SmtpService project
# Build and publish the application
WORKDIR "/src/src/Services/AliasVault.SmtpService"
RUN dotnet build "./AliasVault.SmtpService.csproj" -c $BUILD_CONFIGURATION -o /app/build
# Publish the application to the /app/publish directory in the container
FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "./AliasVault.SmtpService.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
COPY --from=build /app/publish .
ENTRYPOINT ["dotnet", "AliasVault.SmtpService.dll"]

View File

@@ -73,7 +73,7 @@ public class DatabaseMessageStore(ILogger<DatabaseMessageStore> logger, Config c
if (toAddressesFailCount == toAddressesCount)
{
// No valid recipients given.
logger.LogWarning("No valid recipients in email, returning error to sender.");
logger.LogInformation("No valid recipients in email, returning error to sender.");
return SmtpResponse.NoValidRecipientsGiven;
}
}
@@ -291,7 +291,7 @@ public class DatabaseMessageStore(ILogger<DatabaseMessageStore> logger, Config c
if (toAddress is null || !config.AllowedToDomains.Contains(toAddress.Host.ToLowerInvariant()))
{
// ToAddress domain is not allowed.
logger.LogWarning(
logger.LogInformation(
"Rejected email: email for {ToAddress} is not allowed. Domain not in allowed domain list.",
toAddress?.User + "@" + toAddress?.Host);
return false;

View File

@@ -29,14 +29,14 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="NUnit" Version="4.2.2" />
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
<PackageReference Include="NUnit.Analyzers" Version="4.4.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Playwright.NUnit" Version="1.48.0" />
<PackageReference Include="Microsoft.Playwright.NUnit" Version="1.49.0" />
<PackageReference Include="coverlet.collector" Version="6.0.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

View File

@@ -22,7 +22,7 @@
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.2"/>
<PackageReference Include="MailKit" Version="4.8.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0"/>
<PackageReference Include="NUnit" Version="4.2.2"/>
<PackageReference Include="NUnit.Analyzers" Version="4.4.0"/>
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />

View File

@@ -31,7 +31,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="NUnit" Version="4.2.2" />
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
<PackageReference Include="NUnit.Analyzers" Version="4.4.0">

View File

@@ -13,16 +13,11 @@ RUN dotnet restore "src/Utilities/AliasVault.InstallCli/AliasVault.InstallCli.cs
# Copy the entire source code
COPY . .
# Build the project
RUN dotnet build "src/Utilities/AliasVault.InstallCli/AliasVault.InstallCli.csproj" \
-c "$BUILD_CONFIGURATION" -o /app/build
FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "src/Utilities/AliasVault.InstallCli/AliasVault.InstallCli.csproj" \
# Build and publish in one step
RUN dotnet publish "src/Utilities/AliasVault.InstallCli/AliasVault.InstallCli.csproj" \
-c "$BUILD_CONFIGURATION" -o /app/publish /p:UseAppHost=false
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
COPY --from=build /app/publish .
ENTRYPOINT ["dotnet", "AliasVault.InstallCli.dll"]