Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
271 changes: 271 additions & 0 deletions VMSetup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
# Deploy Project 2 to the group VM

This guide assumes the group VM is Ubuntu, Apache is already serving Project 1,
and you can log in over SSH. Replace `XX`, `NTNU-USERNAME`, `OWNER`, and
`REPOSITORY` with the values for your group and GitHub repository.

Project 2 uses PostgreSQL, not MongoDB or Neo4j. Follow the
[database setup guide](../db/database-setup.md) to install and populate it.
The backend and database should run on the VM; the browser-based frontend must
use the VM's hostname to reach the backend.

> **Current project status:** `backend/src/index.ts` is still a placeholder that
> only logs a message, and `frontend/src/App.tsx` is still the Vite starter
> screen. The deployment steps below prepare the VM and publish the frontend,
> but the GraphQL API and application UI must be implemented before the project
> can provide its intended functionality.
## 1. Log in and install Node.js

Connect to your group's VM:

```bash
ssh NTNU-USERNAME@it2810-XX.idi.ntnu.no
```

Install the tools needed to clone and build the project:

```bash
sudo apt update
sudo apt install -y curl ca-certificates git build-essential
```

Install Node.js for your own user with `nvm`. Do not use `sudo` for `nvm`,
Node.js, npm, or pnpm commands.

```bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
touch ~/.bashrc
cat >> ~/.bashrc <<'EOF'
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
EOF
if [ ! -f ~/.profile ] && [ ! -f ~/.bash_profile ] && [ ! -f ~/.bash_login ]; then
printf 'if [ -f "$HOME/.bashrc" ]; then\n . "$HOME/.bashrc"\nfi\n' > ~/.profile
fi
source ~/.bashrc
nvm install --lts
nvm alias default 'lts/*'
node --version
npm --version
```

The install script may report that it could not find a profile file; the
commands above create the Bash startup files and load `nvm` in the current
session. `npm` is installed together with Node.js, so do not install it
separately with `apt`.

## 2. Give the VM SSH access to GitHub

Run these commands as your normal VM user. If prompted for a passphrase, set
one and remember it; do not share or copy the private key.

```bash
ssh-keygen -t ed25519 -C "NTNU-USERNAME@project2-vm"
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
cat ~/.ssh/id_ed25519.pub
```

Copy the displayed **public** key. In GitHub, open **Settings → SSH and GPG
keys → New SSH key**, give it a recognizable title such as `Project 2 VM`, and
paste the public key. Never paste or upload `~/.ssh/id_ed25519` (the private
key).

Verify the connection from the VM:

```bash
ssh -T git@github.com
```

The first connection may ask you to confirm GitHub's host key. Confirm only
after checking that the host is `github.com`. GitHub may report that shell
access is unavailable; that is expected if it also confirms authentication.

Clone the repository using its SSH URL:

```bash
git clone git@github.com:OWNER/REPOSITORY.git ~/project2
cd ~/project2
```

If the repository is private, the GitHub account associated with the SSH key
must have access to it.

## 3. Install dependencies and build the backend

This repository uses pnpm workspaces. Install pnpm under the Node version
managed by `nvm`, then install the locked dependencies:

```bash
npm install --global pnpm@10
cd ~/project2
pnpm install --frozen-lockfile
```

Create the backend environment file and set the password to the PostgreSQL
password configured in the database setup:

```bash
cp backend/.env.example backend/.env
nano backend/.env
```

If `cp` reports that `backend/.env.example` does not exist, do not guess the
environment variables. First verify that the VM has the intended repository
and branch:

```bash
cd ~/project2
git remote -v
git branch -vv
git log -1 --oneline
git ls-files backend/.env.example
```

The repository layout should match the project you intend to deploy. If the
remote, branch, or layout differs, resolve that before proceeding. If the
repository is correct but has no example file, inspect the backend source and
configuration for the environment variable names it actually reads, then
create `backend/.env` with those names. Do not commit `.env` or put real
credentials in a tracked example file.

The file should contain values like these:

```dotenv
DATABASE_URL=postgresql://gameapp:YOUR_PASSWORD@localhost:5432/gamesdb
PORT=3001
```

Keep `backend/.env` private; do not commit it or share its database password.
If the password contains URL-reserved characters, URL-encode them in
`DATABASE_URL`.

Build the TypeScript backend:

```bash
pnpm --filter backend build
```

The backend's `build` script compiles TypeScript to `backend/dist`; its
`start` script runs the compiled JavaScript. The running application must load
the environment variables (for example, with `dotenv/config`) and open its
GraphQL HTTP endpoint before it can serve requests.

## 4. Run the backend after logout

Use PM2 to keep the backend process running under your VM user:

```bash
npm install --global pm2
cd ~/project2/backend
pm2 start dist/index.js --name project2-backend
pm2 save
pm2 startup
```

`pm2 startup` prints a command that must be run with `sudo` to enable startup
after a VM reboot. Copy and run that exact command, then save the process list
again:

```bash
pm2 save
```

Useful process commands:

```bash
pm2 status
pm2 logs project2-backend
pm2 restart project2-backend
pm2 stop project2-backend
```

Always start, inspect, and stop this PM2 process as the same VM user. Check
that the backend is not already running before attempting to start another
copy.

## 5. Build and publish the frontend at `/project2`

The Vite production build uses `/project2/` as its base path when served from
Apache under that subdirectory. This is configured in
`frontend/vite.config.ts`; the local development server continues to use `/`.

Build the frontend from the repository root:

```bash
cd ~/project2
pnpm --filter frontend build
```

Copy the *contents* of the build output to a new Project 2 directory. This does
not replace Project 1:

```bash
sudo install -d -o "$USER" -g www-data /var/www/html/project2
sudo cp -a frontend/dist/. /var/www/html/project2/
```

The frontend should then be available at:

```text
http://it2810-XX.idi.ntnu.no/project2/
```

## 6. Point the browser frontend at the backend

The frontend runs in each visitor's browser. Therefore `localhost` in a
frontend API URL means the visitor's own computer, **not** the VM. Configure
the frontend to use the VM hostname and the actual GraphQL endpoint, for
example:

```text
http://it2810-XX.idi.ntnu.no:3001/graphql
```

Use the route and port the implemented backend actually serves. The backend
must listen on an address reachable from the browser (often `0.0.0.0` when
connecting directly to port `3001`), and the port must be allowed by the
network. Alternatively, configure Apache as a reverse proxy so the browser can
use the VM's normal HTTP port; that requires an Apache proxy configuration
matching the actual GraphQL route. Do not expose PostgreSQL's port for this:
the backend connects to PostgreSQL locally using `localhost`.

Once the frontend API client supports configuration, provide its URL at build
time, for example:

```bash
VITE_GRAPHQL_URL=http://it2810-XX.idi.ntnu.no:3001/graphql pnpm --filter frontend build
```

The frontend code must read `VITE_GRAPHQL_URL` for this setting to take effect.
Vite embeds `VITE_` variables into the built client, so never put passwords or
other secrets in them.

## 7. Update and troubleshoot

To deploy a later version, first update the checkout and rebuild:

```bash
cd ~/project2
git pull
pnpm install --frozen-lockfile
pnpm --filter backend build
pnpm --filter frontend build
```

Then restart the backend and copy the new frontend build:

```bash
pm2 restart project2-backend
sudo cp -a frontend/dist/. /var/www/html/project2/
```

Check processes and backend logs with `pm2 status` and
`pm2 logs project2-backend`. Check Apache with
`sudo systemctl status apache2`. A database connection failure should be
debugged on the VM: confirm PostgreSQL is running and that `DATABASE_URL`
matches the local database and credentials. A browser API connection failure
often means the frontend still uses `localhost`, the backend is not listening
on a reachable address, the chosen port is blocked, or the configured GraphQL
route does not match the server.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
Layers3,
Network,
Eye,
FileText,
} from "lucide-react";

import type { LucideIcon } from "lucide-react";
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/pages/SavedItems/SavedItems.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

import { ArrowRight, Bookmark, Crosshair, Database, Lock, Search, Settings, Shield, Signal, Users } from "lucide-react";
import { ArrowRight, Bookmark, Crosshair, Database, Lock, Settings, Shield, Signal, Users } from "lucide-react";
import { useState } from "react";
import "./SavedItems.css";

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/pages/Techniques/TechniqueDetailed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import TechniqueOverview from "../../components/techniques/specificTechnique/Tec
import SubTechniques from "../../components/techniques/specificTechnique/TechniqueSubTechnique/SubTechniques";
import RelatedThreatActors from "../../components/techniques/specificTechnique/RelatedThreatActors/RelatedThreatActors";
import AssociatedSoftware from "../../components/techniques/specificTechnique/AssociatedSoftware/AssociatedSoftware.tsx";
import worldMap from "../../assets/tungnguyen0905-technology-7111765.jpg";
//import worldMap from "../../assets/tungnguyen0905-technology-7111765.jpg";
import "./TechniqueDetailed.css";

const subTechniques = [
Expand Down