Login

Please fill in your details to login.





setting up a linux vps for teaching web development

Node.js, PostgreSQL and Drizzle ORM Setup Guide
As a computing teacher, moving students from writing code on their local machines to deploying on a production Linux Virtual Private Server (VPS) is a massive leap.

In this guide, we are building a miniature Platform-as-a-Service (PaaS) - similar to professional environments like AWS or Heroku - using a very cheap VPS from IONOS. In industry, software engineers do not set up their own database servers or configure firewalls. Instead, a DevOps engineer (in this case, you, the teacher) prepares a secure "sandbox" and a database, and the developer (the student) builds their application within those strict boundaries.

When teaching server-side development, educators constantly battle between making things "easy" (which often involves hiding how things actually work) and making things "realistic" (which can overwhelm students). Hopefully, this stack will ease that overwhelm.

The Teaching Tech Stack Overview


Operating System: Linux Virtual Private Server (VPS)
Database Engine: PostgreSQL
Runtime Environment: Node.js
Web Framework: Express
Object-Relational Mapper: Drizzle ORM
Templating Engine: EJS (Embedded JavaScript)

Here is a breakdown of why the architecture we will build is an exceptional choice for students, how it compares to other leading development stacks, and its standing in the modern industry.

1
Why is this a best pedagogical approach for students to learn server-side development?

No "Magic": Modern frameworks often use "magic" - they hide the server configuration behind the scenes. By building a raw Express server, students explicitly write the code that listens to a port, accepts an HTTP request, queries a database, and returns an HTML response. They learn the actual mechanics of the web.

The MVC Pattern: By introducing EJS templating, you have naturally forced the students into a Model-View-Controller (MVC) architecture. The database schema is the Model, the EJS file is the View, and the Express
index.ts
file is the Controller. This is a foundational computer science concept.

Single Language: Students only need to learn JavaScript/TypeScript. They do not need to learn a completely different language for the database logic, the server logic, and the browser logic.

2
The Alternatives: Comparing Leading Development Stacks

It is very common to wonder if we should just use PHP, jump straight into React, or adopt other industry heavyweights like Python or Java. Here is how this proposed setup compares:

Why not PHP?

PHP was the undisputed king of beginner web development for two decades (the classic LAMP stack). It is incredibly easy to deploy because you just drop a
.php
file onto a server and it works.

Justification: PHP can encourage bad habits in beginners, such as writing raw SQL queries directly inside HTML loops, leading to messy, unmaintainable code. Whilst modern PHP (like Laravel) is excellent, learning Node.js and TypeScript prepares students for a wider variety of modern enterprise roles.

Why not React?

React is a front-end library. Whilst you can build full-stack applications with frameworks like Next.js, doing so introduces a massive wall of complexity.

Justification: If you teach React first, students spend all their time battling "State", "Hooks", "UseEffect", and "Virtual DOMs". They get completely distracted from learning what a server actually is. EJS allows them to write standard HTML and focus 100% of their brainpower on learning database queries and server routing. React is a fantastic subject for a subsequent term, once they understand the basics of a backend API.

Why not Python (Django or Flask)?

Python is highly praised as a beginner-friendly programming language which students will have likely learnt before in their education.

Justification: For teaching web architecture, its leading framework (Django) is heavily opinionated and relies heavily on "magic" - it automatically generates admin panels and handles database schemas for you. This hides the underlying HTTP mechanics from students. Whilst Flask is more lightweight and similar to Express, using Python on the backend forces students to constantly context-switch between Python syntax and JavaScript syntax (for any interactive frontend elements).

Why not Java (Spring Boot) or C# (.NET)?

These are the absolute heavyweights of the corporate enterprise world, powering the majority of banking and large-scale commercial systems.

Justification: They are extremely verbose and possess a notoriously steep learning curve. Setting up the boilerplate configurations and strict object-oriented structures for a Spring Boot application can consume an entire lesson, whereas a Node/Express server can be launched in just ten lines of code. They are excellent for advanced university modules, but overwhelming for an initial foray into server architecture.

Why not Ruby on Rails?

Rails pioneered the modern, rapid-development MVC framework.

Justification: Its core philosophy is "Convention over Configuration". It makes so many assumptions on behalf of the developer that students often have no idea how the server is actually processing the network requests. It is fantastic for rapid prototyping in the industry, but less effective for teaching the raw fundamentals of how web servers operate.

3
Where does this architecture stand in the industry?

This setup perfectly mirrors a modern, professional enterprise environment.

The PaaS Sandbox (The VPS Setup): By giving students a locked-down user account on a Linux server, you are simulating exactly how a junior developer operates at a major tech company. They are given a secure "container" or sandbox to work in, managed by a DevOps engineer (you).
Node.js and Express: This remains one of the most widely used server architectures in the world. It powers backends for companies like Netflix, Uber, and PayPal.
PostgreSQL: This is currently the industry-favourite relational database. It is renowned for its reliability and enterprise-grade features.
Drizzle ORM: This is the most modern, cutting-edge tool in this stack. In the last couple of years, the industry has aggressively shifted towards "Type-Safe" ORMs. Drizzle is currently the darling of the TypeScript community, heavily favoured over older tools because it is incredibly fast and prevents developers from making silly database errors.

By adopting this structure, we achieve two things:

Safe Failure: Students can install libraries and completely break their own environment without affecting the global server or other students. By isolating their workspace, we contain any potential damage.
Guaranteed Supervision: We will use Access Control Lists (ACLs) to ensure that no matter what permissions a student alters, you will always have a read-only window into their code for grading and debugging.

By using this stack, you are teaching fundamental, transferrable web concepts (HTTP, routing, MVC) whilst using modern, highly employable enterprise tools (TypeScript, PostgreSQL, Drizzle). It strikes the perfect balance for a classroom environment.

...for the teacher


Server Setup


We begin as the
root
user. This is the absolute administrator of the Linux system. We will install our system-wide database and immediately create a dedicated
webmaster
account for you to use day-to-day, adhering to the cybersecurity principle of least privilege. Operating as root is dangerous, so we want to use it as little as possible.

Phase 1: PostgreSQL Installation


PostgreSQL is an enterprise-grade relational database. It runs as a system-wide background service (a daemon), so it must be installed by root to ensure it has the correct permissions to start automatically when the server powers on.

1
Update Package Index

Linux uses a package manager (
apt
) to download software from central repositories. We must first update its local index to ensure it pulls the absolute latest, most secure versions of the software, rather than relying on an outdated cache:

sudo apt update


2
Apply Security Upgrades

Apply any pending security upgrades and bug fixes to the core operating system packages to ensure a stable and secure foundation before we install anything new:

sudo apt upgrade -y


3
Install ACL Utilities

Some minimal Linux server installations do not include the tools required to manage Access Control Lists by default. We must install the
acl
package so we can securely manage and isolate student folder permissions later on:

sudo apt install acl -y


4
Install PostgreSQL

Install the database server and its contrib package. The contrib package is highly recommended as it contains official, highly useful cryptographic extensions and administrative utilities that professional database administrators rely on for advanced data manipulation:

sudo apt install postgresql postgresql-contrib -y


5
Verify Service Status

Ask the Linux service manager (
systemctl
) to confirm the database engine has booted successfully and is actively running in the background:

sudo systemctl status postgresql


If it says "active (running)", press q to exit the screen and return to the terminal prompt.

6
Enable Automatic Boot

Ensure the database starts automatically if the server ever reboots or loses power. Without this command, a server restart would leave your database offline until you manually intervened:

sudo systemctl enable postgresql


Phase 2: Teacher Account Creation


We will now create your daily driver account. This is the account you will use to manage the server on a day-to-day basis.

1
Create the Webmaster User

The
-m
flag instructs Linux to automatically generate a home directory for the user, and the
-s /bin/bash
flag assigns them a standard, user-friendly command-line shell environment:

sudo useradd -m -s /bin/bash webmaster


2
Grant Administrative Privileges

Add the webmaster to the
sudo
group. This allows you to temporarily borrow root powers when provisioning students, without needing to actually log in as the highly dangerous root user. You will simply type "sudo" before commands that require administrative oversight:

sudo usermod -aG sudo webmaster


3
Set the Webmaster Password

By default, the Linux
useradd
command creates the account but does not assign it a password. Without a password, the system will prevent the webmaster from using
sudo
for administrative tasks later. We must set one now whilst we are still operating as root:

passwd webmaster


You will be prompted to type a secure password. Please note that Linux will not display any characters or asterisks whilst you type - this is a standard security feature to prevent shoulder-surfing. Type your chosen password, press ENTER, and retype it to confirm.

4
Switch Context

Drop your root session and switch to your new teacher account. The hyphen is important because it ensures you load the full environment profile of the webmaster user:

su - webmaster


Phase 3: Claiming the Territory


You are now operating as the
webmaster
. Before students join, we need to create the main directory that will house all student projects and take permanent ownership of it. This saves us from having to use root privileges every single time a new student arrives in the class.

1
Construct the Root Web Directory (www)

In the Linux Filesystem Hierarchy Standard, the
/opt
directory is reserved for optional, self-contained software packages, making it the perfect place for custom web applications. We will temporarily use
sudo
to create our
www
directory there. The
-p
flag ensures parent directories are created if they do not exist:

sudo mkdir -p /opt/www


You will be asked to enter the secure 'webmaster' password you created earlier.

2
Take Ownership

Right now, the root user owns that directory because we used sudo to create it. We will change the ownership so that the
webmaster
account has total, unquestioned authority over it:

sudo chown webmaster:webmaster /opt/www


3
Open the Firewall Ports

By default, Linux servers block incoming network traffic on non-standard ports to protect the system from malicious access. Because your students will be running their Express web servers on various assigned development ports, you can explicitly instruct the Uncomplicated Firewall (UFW) to allow external web traffic to reach a block of ports (for example, 5000 to 5100). This preemptive step saves you from having to open a new port every time you provision a new student.

sudo ufw allow 5000:5100/tcp


Phase 4: Student User and Workspace Creation


Whenever a new student joins the class, you will follow these steps to provision their secure sandbox and database. Because you now own
/opt/www
, creating their project folder is simple. We will use a student named "turing" as our example.

1
Create the Student Account

Create a restricted Linux user for the student. This completely isolates their environment from other students and prevents them from modifying global system files:

sudo useradd -m -s /bin/bash turing


2
Set the Student Password

Just like the webmaster account earlier, the Linux
useradd
command creates the student's account but leaves it locked without a password. Since the student will need to log in via SSH later, you must set an initial password for them now:

sudo passwd turing


You will be prompted to type a password. Linux will not display any characters whilst you type. Enter a secure password, press ENTER, retype it to confirm, and securely share these credentials with the student later.

3
Construct the Sandbox

Create a dedicated folder for their web project. Notice you do not need
sudo
for this command because you already own the parent
www
folder!

mkdir /opt/www/turing


4
Assign Ownership

Make the student the owner of their folder so they can write code inside it, but set the group to
webmaster
. The
-R
flag ensures this ownership applies recursively to anything inside the folder:

sudo chown -R turing:webmaster /opt/www/turing


5
Apply Access Control Lists (ACLs)

Standard Linux permissions allow the owner of a folder to lock everyone else out. To prevent the student from locking you out of their code, we apply an Access Control List (ACL). This creates an unbreakable, overriding rule guaranteeing the
webmaster
user can always read and execute files inside this directory for grading purposes.

First, apply the rule to the folder so you have access right now:

sudo setfacl -R -m u:webmaster:rx /opt/www/turing


Next, set it as the "default" rule. This guarantees that any new file or folder the student creates in the future automatically inherits this supervisory access:

sudo setfacl -R -d -m u:webmaster:rx /opt/www/turing


Phase 5: Database Provisioning


1
Access the SQL Terminal

Impersonate the PostgreSQL superuser to provision the student's database. This is a secure way to access the database engine without needing to use the database root user:

sudo -u postgres psql


2
Create Database

Create the physical container for the student's data. Every student gets their own isolated database to prevent data overlap:

CREATE DATABASE turing_db;


Remember the database name you have assigned as you will have to give this to the student as part of their connection string later.

3
Connect to the Database

Connect to it immediately. This is a vital step because security policies must be applied directly within the target schema:

\c turing_db


4
Provision PostgreSQL User Account

Create the student's database identity. Ensure you choose a secure, unique password for each student to prevent them from accessing each other's data:

CREATE USER turing_user WITH PASSWORD 'secure_turing_password';


Remember the specific database username and database password you have assigned to the student because you will need to provide this as part of their connection string later.

5
Grant Rights

Grant them full administrative rights over their specific database, whilst keeping them locked out of the rest of the database engine:

GRANT ALL PRIVILEGES ON DATABASE turing_db TO turing_user;


6
Unlock Public Schema

In modern versions of PostgreSQL, default permissions were tightened. We must explicitly grant permission for the student to modify the default table schema (the "public" schema), otherwise their application will crash when it tries to create new tables:

GRANT ALL ON SCHEMA public TO turing_user;


7
Exit SQL

Return to the standard Linux command line terminal:

\q


CRITICAL: Each student will need access to SEVEN facts before they can begin:
1
their server username (for SSH access).
2
their server password (for SSH access).
3
the database name you have created for them within PostgreSQL.
4
their database username.
5
their database password.
6
the server IP address.
7
the assigned port number.

At this point, you hand over to the student. The student logs in via SSH using their credentials. The following steps are written for the student to follow.

...for the learner


Your Development Sandbox


Welcome to your production sandbox! Your teacher has provided you with an isolated workspace and a database. You will now set up a production development environment entirely within your own user account. This mirrors how professional developers operate in enterprise cloud environments.

Phase 1: Node.js and Environment Setup


1
Log in with SSH

Your teacher will provide you with an IP address or a domain name for the main server on which your workspace is hosted. SSH (Secure Shell) is a cryptographic network protocol that allows you to operate network services securely over an unsecured network. Using Windows CMD / PowerShell or Terminal, type the following command and press the ENTER key replacing
{user}
with your server username and
{ip_address}
with the IP or domain name your teacher has given you.

ssh {user}@{ip_address}


You will be asked for your server password before you are granted access but you won't be able to see or check what you are typing. This is a deliberate security feature to prevent people looking over your shoulder from guessing the length of your password. Be careful, press the ENTER key afterwards, and keep your fingers crossed you see the Linux prompt.

2
Navigate to Your Workspace

You will end up in your userspace (your home directory) on the server at a prompt starting with a tilde (
~
), but this is NOT where your development workspace is located. We will now move into the dedicated web directory your teacher provisioned for you. Type the following followed by the ENTER key replacing
{username}
with your server username.

cd /opt/www/{username}


3
Install Node Version Manager (NVM)

We will now install your main development tool, Node.js, but first, we need to install another piece of software called the Node Version Manager (NVM). We use NVM because it installs Node.js securely within your own home directory, preventing permission errors and allowing us to install more current versions than the Linux operating system provides. When multiple developers use a server, installing Node globally often leads to severe package conflicts. NVM bypasses this entirely by placing the runtime strictly within your personal profile.

Download and run the installer using the
curl
command, which pulls the script from the internet and pipes it directly into
bash
for execution:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash


4
Reload Configuration

The installation script has modified your terminal's hidden configuration file, but your current session does not know that yet. Make the terminal recognise the new tool by reloading the file:

source ~/.bashrc


You should now be able to check that NVM is working by typing...

nvm -v


...and pressing ENTER. The command should return the NVM version number.

5
Install Node.js

Install version 20 (which is the stable Long Term Support release, meaning it receives critical security updates for an extended period):

nvm install 20


6
Activate Node.js

Activate your new installation for the current session. This tells your Linux terminal exactly where to find the Node executable whenever you try to run JavaScript code.

nvm use 20


Phase 2: Application Architecture


You will now build a modern web application using the Express framework, Drizzle ORM (Object-Relational Mapper), and the EJS templating engine.

1
Initialise the Project

Create a
package.json
file. Think of this file as the central manifest for your project - it tracks your project's name, version, and a list of all the third-party libraries your code will depend on. The
-y
flag simply accepts all the default configuration options. Make sure you are still in your workspace directory (
/opt/www/{username}
) and run the following command:

npm init -y


You should receive a message outlining the contents of the manifest.

2
Install Runtime Libraries

Install your core runtime tools. Drizzle ORM acts as a translator between our TypeScript code and the database, protecting against SQL injection attacks. The
postgres
package handles the network connection,
express
is our web server framework,
dotenv
is a crucial security module that loads sensitive passwords from hidden files and finally,
ejs
(Embedded JavaScript) is a templating engine that allows us to separate our backend logic from our frontend HTML files:

npm install drizzle-orm postgres dotenv express ejs


Wait for the command to install all the dependencies - you'll see a spinning cursor whilst it's working. If you run a directory listing when you get back control with
ls -la
you should now see a
node_modules
directory which contains all your runtime tools, ready for action.

3
Install Development Tools

Next, we install our Development Dependencies. These are tools required to compile and manage the software whilst you are building it, but they are not needed by the final running server. We are installing the TypeScript compiler, the
tsx
live-execution environment, and type definitions to provide code auto-completion:

npm install -D drizzle-kit typescript tsx @types/node @types/express


4
Configure TypeScript

Generate a configuration file to enforce strict type-safety. This creates a
tsconfig.json
file which dictates the rules the TypeScript compiler must follow when checking your code for errors:

npx tsc --init


5
Create the Environment File

We never hardcode passwords in our logic - instead, we store them in a hidden file. In Linux systems, any file that begins with a dot (like
.env
) is automatically hidden from standard directory listings, adding a layer of protection. This also ensures you never accidentally commit your database credentials to a public source code repository.

nano .env


Paste the connection string your teacher gave you (which should have specific replacements for
{database_user}
,
{database_password}
and
{database}
):

DATABASE_URL=postgresql://{database_user}:{database_password}@localhost:5432/{database}


Then save using Ctrl + o, ENTER, Ctrl + x.

6
Create Drizzle Configuration

Tell the Drizzle toolkit where to find your database blueprint. It needs this configuration file so it knows how to generate the correct SQL commands later on. We must import
dotenv
here so Drizzle knows how to read your hidden password file!

nano drizzle.config.ts


Copy and paste following:

import { defineConfig } from "drizzle-kit";
import 'dotenv/config';

export default defineConfig({
  schema: "./src/schema.ts",
  out: "./drizzle",
  dialect: "postgresql",
  dbCredentials: {
    url: process.env.DATABASE_URL!,
  }
});


...then save the file by pressing CTRL+o then ENTER then CTRL+x.

7
Define the Schema

Create a source folder to keep your application logic neatly separated from configuration files:

mkdir src


Define your database tables using TypeScript schema. A schema is the architectural blueprint of your database. Instead of writing raw SQL commands, we define our tables using strict TypeScript objects, ensuring that if we make a mistake, the compiler will catch it before the code runs:

nano src/schema.ts


Copy and paste the following:

import { pgTable, serial, text } from "drizzle-orm/pg-core";

export const users = pgTable("users", {
  id: serial("id").primaryKey(),
  name: text("name").notNull(),
});


...then save the file by pressing CTRL+o then ENTER then CTRL+x.

8
Establish the Database Connection

Create a connection pool to allow your app to handle multiple users simultaneously. A connection pool acts like a waiting room; instead of opening and closing a new database connection for every single web visitor (which is very slow), it keeps a "pool" of connections permanently open and ready to process data efficiently:

nano src/db.ts


Copy and paste the following:

import { drizzle } from "drizzle-orm/postgres-js";
import postgres from "postgres";
import * as schema from "./schema";
import 'dotenv/config';

const client = postgres(process.env.DATABASE_URL!);
export const db = drizzle(client, { schema });


...then save the file by pressing CTRL+o then ENTER then CTRL+x.

9
Push the Schema

We use
drizzle-kit
to translate the TypeScript blueprint into actual SQL tables automatically. This remarkable tool reads your
schema.ts
file, connects to your remote database using the credentials in your
.env
file, and executes the raw SQL commands required to construct the tables physically:

npx drizzle-kit push


If everything goes to plan, you should see two lovely ticks as confirmation:

[✓] Pulling schema from database...
[✓] Changes applied


Phase 3: Create the view and controller


1
Create the HTML Template (EJS)

To keep our frontend code clean, we will create a dedicated folder for our HTML templates (called "views") and write a standard HTML file. The EJS templating engine will allow us to inject our database variables into this HTML later using special
<%= ... %>
tags.

mkdir views && nano views/index.ejs


Copy and paste the following standard HTML structure...

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>My Student Server</title>
  <style>
    body { font-family: sans-serif; padding: 20px; color: #333; }
    pre { background: #eee; padding: 15px; border-radius: 8px; overflow-x: auto; }
    h1 { color: #2563eb; }
  </style>
</head>
<body>
  <h1>Student Server Active!</h1>
  <p>Database connected successfully. Found <%= allUsers.length %> users.</p>
  
  <h2>Raw Database Output:</h2>
  <pre><%= JSON.stringify(allUsers, null, 2) %></pre>
</body>
</html>


...then save the file by pressing CTRL+o then ENTER then CTRL+x

2
Write the Web Server Script

Create your main application file. This is the central entry point that will launch your Express web server, connect to the database, and render the HTML template you just created:

nano index.ts


Copy and paste the following, replacing
{port}
with the server port you have been assigned by your teacher...

import express from "express";
import { db } from "./src/db";
import { users } from "./src/schema";

const app = express();
const PORT = {port}; 

app.set("view engine", "ejs");
app.use(express.json());

app.get("/", async (req, res) => {
  try {
    await db.insert(users).values({ name: "Alan Turing" });
    const allUsers = await db.select().from(users);
    res.render("index", { allUsers });
  } catch (error) {
    console.error("Database error:", error);
    res.status(500).send("An error occurred whilst fetching data.");
  }
});

app.listen(PORT, "0.0.0.0", () => {
  console.log(`🚀 Student server running on port ${PORT}`);
});


...then save the file by pressing CTRL+o then ENTER then CTRL+x.

Phase 4: Launch the server and test


1
Launch the Application

Start your web server. It will remain awake, continuously listening for incoming network traffic. We use
tsx
so that we can run the TypeScript file directly without having to compile it to JavaScript manually beforehand:

npx tsx index.ts


If all goes well, you should see this message (with your allocated port number):

🚀 Student server running on port {port}


2
View your application

Open a web browser on your desktop. Navigate to
http://{ip_address}:{port}
(ensuring you include the colon and the port number). Ignore the security warning if one appears, as we have not yet set up an SSL certificate, and you should see the beautifully formatted output of your first web application!

3
Understanding Foreground Processes

It is vital to understand that your web server is currently running as a "foreground process". This means its lifecycle is tied directly to your active SSH terminal session.

If you close your terminal window right now, the Node.js process will be immediately killed, and your website will go offline. This isn't necessarily a bad thing in a development environment because it means that no-one can interact with your code whilst you are AFK. However, in a professional production environment, software engineers use tools called "Process Managers" (like PM2 or systemd) to push these applications into the background so they run permanently and automatically restart if they crash or the server restarts. For now, simply leave your terminal window open whilst you are actively developing and testing your code!

You have successfully deployed a production-grade web application in a secure sandbox

...for the teacher


Decommissioning a Student Account


At the end of the academic year, or if a student leaves the course, you will need to completely purge their environment to free up server resources (memory, storage, and network ports).

This process is irreversible. Once you execute these commands, the student's code, database, and account history will be permanently destroyed. We will continue using the student "turing" as our example.

Ensure you are logged in as the
webmaster
account before beginning.

Phase 1: Terminate Active Processes


Before deleting anything, we must forcefully stop any web servers or background scripts the student might have left running. If you try to delete an account whilst its processes are still active, Linux will throw an error, and the database might refuse to be deleted because it is still "in use".

Ask Linux to kill every single process owned by the student:

sudo pkill -u turing


Phase 2: System and Filesystem Purge


Now that the student's applications are dead, we can safely remove their presence from the Linux operating system.

1
Delete the User Account

Remove the student's Linux identity and their home directory. The
-r
flag ensures their personal profile folder is completely wiped:

sudo userdel -r turing


2
Destroy the Sandbox

Delete the dedicated web directory where they stored their Express application. The
-rf
flag tells Linux to recursively force the deletion of the folder and everything inside it without asking for confirmation:

sudo rm -rf /opt/www/turing


Phase 3: Database Purge


Finally, we need to remove their database and their SQL user account to free up storage and ensure their specific credentials can no longer be used.

1
Access the SQL Terminal

Impersonate the PostgreSQL superuser:

sudo -u postgres psql


2
Drop the Database

Completely destroy the physical database container and all the tables within it:

DROP DATABASE turing_db;


3
Drop the User

Remove the student's database identity. (Note: You must drop the database before dropping the user, as PostgreSQL will not let you delete a user who still owns a database):

DROP USER turing_user;


4
Exit SQL

Return to the standard terminal:

\q


The student has now been completely purged from the server! Their assigned port is free to be reallocated to a new student.
Last modified: April 7th, 2026
The Computing Café works best in landscape mode.
Rotate your device.
Dismiss Warning