This website hosts my basic information as well as my photography portfolio. It started as a simple idea and it evolved into a fairly complex application that is in the over-engineered side. However, it was very satisfying to build, I learned a few new things and I'm happy to see that is 90% Rust, although I had to move the photo stack js code into a different repository to keep it JS from taking over :)
-
Rust >= 1.78.0
-
sqlx-cli:
# The DB CLI cargo install sqlx-cli # For recompilation on code update while developing cargo install --locked bacon
Run the setup script after cloning. It configures git hooks that prevent committing unencrypted vault files.
./scripts/unix/setup-dev.shPrepare the environment variables by creating an .env file
cp .env.example .env
cp .cargo/config.toml.example .cargo/config.tomlThe .cargo/config.toml requires an update, replace the needed keys for AWS.
Since this Site won't have a UI or any kind of management outside my computer, all the CRUD operations will happen locally, and I'll just ship the DB on every release, I have to have someway of managing it, so a simple CLI will do.
This CLI reads the EXIF information using exiftool, then stores it in the DB and uploads the file to an S3 Bucket.
For this, make sure to run the exiftool installation
./scripts/unix/exiftool.shFor Windows
scripts\windows\exiftool.batAnd to run the CLI
cargo run -p cli-victorhqc-com
cargo run -p cli-victorhqc-com -- --helpRun the project
cargo run -p api-victorhqc-com
# With hot reload
baconFirst, install the dependencies the website needs using the web-dependencies.sh
script, just make sure wget is installed, for Mac OSX do it with
brew install wgetAnd then run the script. It will download a copy of tailwindcss and htmx.
We could use a CDN, but time has proven that CDNs go down sometimes, and we want
to avoid problems caused by 3rd parties as much as possible.
./scripts/unix/web-dependencies.shMake sure the API is running and then run the following
# With hot reload
bacon webAdd a new migration
# Move into the core directory
cd ./core
sqlx migrate add -r <name>Run migrations again
sqlx migrate runNote that when adding a new query, the following needs to run
cargo sqlx prepare --workspaceThe service will run in a Linux machine, so targeting that platform is imperative.
Requirements
- Musl Target
rustup target add x86_64-unknown-linux-musl- Musl Linker
brew install FiloSottile/musl-cross/musl-crossCompilation
cargo build --release --target x86_64-unknown-linux-muslTo make sure the API runs smoothly, running stress tests is encouraged.
cargo install drillCopy the script and benchmark file
cp scripts/unix/run.api.example.sh scripts/unix/run.api.sh
cp stress-tests/benchmark.example.yml stress-tests/benchmark.yml
cp stress-tests/benchmark.web.example.yml stress-tests/benchmark.web.ymlAnd replace the values in the script and benchmark file
Make sure the API is running
cargo build --release
./scripts/unix/run.api.sh
./scripts/unix/run.web.shThen run the stress tests
drill --benchmark stress-tests/benchmark.yml --stats
drill --benchmark stress-tests/benchmark.web.yml --statsDeployment uses Ansible. It handles both fresh machine setup and
routine releases. All playbooks live in deploy/.
- Ansible:
brew install ansible - cloudflared: SSH proxy to the server
- The
lattepandaSSH alias configured in~/.ssh/config
Secrets are stored in deploy/inventory/group_vars/all/vault.yml, encrypted with
Ansible Vault.
First time setup:
cd deploy
# Fill in your real values
vi inventory/group_vars/all/vault.yml
# Encrypt the file
ansible-vault encrypt inventory/group_vars/all/vault.ymlTo edit secrets later:
ansible-vault edit inventory/group_vars/all/vault.ymlThis installs packages, creates users, sets up nginx, deploys systemd services, and runs the first deploy.
cd deploy
ansible-playbook playbooks/setup.yml --ask-vault-pass --ask-become-passPass -e install_web_deps=true to also install web dependencies (tailwindcss,
htmx, etc.) before building.
The setup playbook supports tags to run individual roles: common, nginx,
api, web. For example, to only update the nginx configuration:
cd deploy
ansible-playbook playbooks/setup.yml --ask-vault-pass --ask-become-pass --tags nginx --skip-tags buildThe --skip-tags build skips the local compilation step when you only need to
update server configuration.
This builds the project locally, uploads binaries and assets, backs up the database, and restarts the services.
cd deploy
ansible-playbook playbooks/deploy.yml --ask-vault-pass --ask-become-passIf you already ran cargo build --release --target x86_64-unknown-linux-musl
and want to skip the build, add --skip-tags build:
cd deploy
ansible-playbook playbooks/deploy.yml --ask-vault-pass --ask-become-pass --skip-tags buildBoth services run under systemd. Check their status with:
systemctl status victorhqc-api
systemctl status victorhqc-web
