# TJ CSL

This is the documentation site for the TJHSST Computer Systems Lab.

If you are contributing for the first time, please read our [documentation guide](/general/documentation).

For an overview of the Sysadmin program, see the [Sysadmin page](/general).

This is intended for TJHSST Student System Administrators only.


# Services


# Ion

The TJ Intranet platform

## Ion

Ion (<https://ion.tjhsst.edu>) is the next-generation Intranet system used at TJHSST. Using Python, Django, Redis, Postgres, and many other technologies, Ion was developed from the ground up to be simple, well-documented, and extensible.

Ion allows students, teachers, and staff at TJHSST to access student information, manage activity signups, and view information on news and events. [Read more about how Ion is used at Thomas Jefferson](https://ion.tjhsst.edu/about).

{% hint style="info" %}
Note: Ion is not to be referred to as "ION" in capital letters. The correct spelling is "Ion".
{% endhint %}

## History

Ion was completely student-built and was the senior research project of James Woglom (Class of 2016). It was first announced on Wednesday, November 11th, 2015 concurrently with a [tribute to Iodine developers](https://web.archive.org/web/20151111231602/https://iodine.tjhsst.edu/) on the Iodine homepage. [Iodine was](https://twitter.com/TJIntranet/status/664857149324005377) [shut down](https://twitter.com/TJIntranet/status/665273342396604417) the evening of Friday November 13th, and both Iodine and Ion remained inaccessible throughout the weekend. After completing teacher training, Ion was [officially released](https://twitter.com/TJIntranet/status/666356448801251330) at the end of the school day on Monday November 16th, one day before initially planned. It ran its first Eighth Period block successfully [two days later](https://twitter.com/TJIntranet/status/666619609143975936) on Wednesday November 18th.

## Architecture

Ion is a Django application backed by a PostgreSQL database and using Redis to perform in-memory caching. &#x20;

## Contributing

The contact person for Intranet is the [Intranet Lead](/general/sysadmins-list#current-leads).


# Development

{% hint style="info" %}
Knowledge of Git and basic Linux commands is a prerequisite for Ion development.
{% endhint %}

Before continuing, you should probably read about Ion's architecture.

Before continuing, it would also be useful to know Python, Django, and the client-server model (or at least have documentation, references, and tutorials available).

## Resources

{% embed url="<https://en.wikipedia.org/wiki/Client%E2%80%93server_model>" %}

{% embed url="<https://docs.python.org/3/>" %}

{% embed url="<https://docs.djangoproject.com/en/2.1/>" %}

{% embed url="<https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django>" %}


# Overview

This section contains guidance for creating the Ion Development Environment in your own laptop or PC. Please also check out [Ion's setup instructions](https://github.com/tjcsl/ion/blob/master/SETUP.md) for additional guidance. If in doubt, follow the instructions in the official Ion repository.


# Setup

You have two options when it comes to developing for Ion:

{% content-ref url="/pages/-LKatwtRXVU2Pew51f3Z" %}
[Vagrant Setup](/services/ion/development/setup/vagrant-setup)
{% endcontent-ref %}

{% content-ref url="/pages/rF1RsnyeCe5gydE9MeFn" %}
[Docker Setup](/services/ion/development/setup/docker-setup)
{% endcontent-ref %}


# Docker Setup

## Setting up Docker

Docker is one of the two options you have for managing Ion's development environment. Docker is a software platform that is used to build applications using containers. If you want to learn more about Docker, refer to its [documentation](https://docs.docker.com/).

First, download and install Git from [here](https://git-scm.com/downloads) if you are on Windows. Ensure you have an SSH key set up with GitHub by running `ssh -T git@github.com`. You should be greeted by your username. If not, set up an SSH key with GitHub by following [these instructions](https://help.github.com/articles/generating-an-ssh-key/).

Install Docker by following [these instructions](https://www.docker.com/products/docker-desktop/) based on your operating system. For Windows and Mac users, install Docker Desktop.

After installing Git and Docker, fork the [`tjcsl/ion`](https://github.com/tjcsl/ion) repository, and clone your forked Ion repositor&#x79;*.* Once the cloning completed, `cd` into the `intranet` directory. Note that a more up to date guide will be located at <https://tjcsl.github.io/ion/setup/setup.html>.

```
$ git clone git@github.com:<YOUR_GITHUB_USERNAME>/ion.git intranet
$ cd intranet
```

{% hint style="info" %}
Note: if your host machine is running Windows, please run `git config core.autocrlf input` before cloning to prevent line ending issues.
{% endhint %}

Also make sure that Docker Compose is installed along with `docker`, this is important when it comes to building and bringing the development environment to life. Make sure that during this process you are in the config/docker directory.

Run `docker compose build` to get all the dependences that Ion needs, like `redis`, `postgres`, `celery`, etc. This should take a minute or two.

Once after the building is complete, run `docker compose up` to compose the container. You can add `-d` flag to the command if you wish.

### Post Setup

Navigate to [http://localhost:8080](http://localhost:8080/) in the web browser of your choice. If this is the first time composing the container (in which in this case; running `docker-compose up -d` for the first time on that computer), you may have to wait for approximately 60 seconds for it to start running. When presented with the login page, you can login in the default admin account which is `admin`/`notfish`.

### Useful Commands

#### Interacting with the application:

If you need to run a Django command like `makemigrations`, `collectstatic` or `shell_plus`, run `docker exec -it intranet bash` in your terminal. That will give you a shell into the application container. You can also use this to run scripts like `build_sources.sh`. If you need to view the output from or restart `runserver`, run `docker attach application`.

### History

The use of Docker for developing Ion was anticipated for a long time after Ion was first release in 2015. The former Vagrant environment didn't really had a multitude of problems, but the idea of making a VM and configuring the VM was a bit annoying for many Sysadmins and understudies who wanted to build the development environment. The Development of the new environment started in early 2022 when then-understudy Justin Lee (`2025jlee`) developed way to make a Ion Development Environment using Docker. The Docker environment solved some of the problems that Vagrant had, most notably the speed building the environment.

Around early 2023, the Docker environment went through a second round of updating to make the environment more quicker and easier to build.


# Vagrant Setup

## Setting up Vagrant

Vagrant is used to manage Ion's development environment so that it closely resembles the production environment. To get started, download and install git from [here](https://git-scm.com/downloads) if you are running Windows or git is not installed. After that, download and install Virtualbox from [here](https://www.virtualbox.org/wiki/Downloads) and Vagrant from [here](http://docs.vagrantup.com/v2/installation/index.html). When you're installing Vagrant, you should install it on your host OS, running nested VMs is not recommended.

Ensure you have an SSH key set up with GitHub by running `ssh -T git@github.com`. You should be greeted by your username. If not, set up an SSH key with GitHub by following [these instructions](https://help.github.com/articles/generating-an-ssh-key/).

With Vagrant and Virtualbox installed, clone the Ion repository onto the host computer and `cd` into the new directory.  Note that a more up to date guide will be located at <https://tjcsl.github.io/ion/setup/setup.html>.

{% hint style="info" %}
Note: if your host machine is running Windows, please run `git config core.autocrlf input` before cloning to prevent line ending issues.
{% endhint %}

```
$ git clone git@github.com:tjcsl/ion.git intranet
$ cd intranet
```

In the `config/vagrant` directory, copy the file `devconfig.json.sample` to `devconfig.json` and edit the properties in `devconfig.json` as appropriate. Ensure `ssh_key` is set to the same SSH key registered with GitHub (e.g. `id_rsa`). Also make sure that `use_nfs` is set to `true` and `use_vpn` is set to `false`. This will prevent connecting to the CSL VPN.

{% hint style="info" %}
The other values specified in `devconfig.json` are optional. The `ldap_simple_bind_password` is not needed and is a remnant of the old LDAP-based authentication scheme.
{% endhint %}

{% hint style="info" %}
Connecting to the CSL VPN may be necessary to test Kerberos authentication or other functionality that requires connection to CSL services. In that case, `use_vpn` should be set to `true`.
{% endhint %}

Run `vagrant plugin install vagrant-vbguest vagrant-bindfs` If you are on Windows, also run `vagrant plugin install vagrant-winnfsd`.

Run `vagrant up && vagrant reload` and wait while the development environment is set up. When asked to select a network interface for bridging, enter the number corresponding to one that is active. To automatically select this interface in the future, set the "network\_interface" key in `devconfig.json` to the name of the interface you selected (e.g. `"en0: Wi-Fi (AirPort)"`). There may be repeated warnings similar to "`Remote connection disconnect` on the second `vagrant up`. After several minutes they will stop. Once the provisioning process is complete, run `vagrant ssh` to log in to the development box.

Move into the `intranet` directory and run `workon ion` to load the Python dependencies. `workon ion` should always be the first thing you run after you SSH into the development box.

The Git repository on the host computer is synced with `~/intranet` on the virtual machine, so you can edit files within the repo on the host computer with a text editor of your choice and the changes will be immediately reflected on the virtual machine.

### Troubleshooting

If you get a `SIOCADDRT: Network is unreachable` error when running `vagrant up`, you need to start the OpenVPN client.

If you see a `Adding routes to host computer...` message, you probably forgot to start the OpenVPN client.

## Post-Setup

After successfully setting up the Vagrant environment, you will want to actually access your sandbox.

Start by connecting to the Vagrant box using `vagrant ssh`. (Consider running all of the following in a `screen` or `tmux` session.) Make sure you’re in the `intranet` directory, and run `python manage.py migrate`. This will set up the Postgres database.

You can then start the built-in Django web server with `fab runserver`. Now that you are running the development server, open a browser to <http://127.0.0.1:8080> and log in. If it fails, check the output of `manage.py runserver`.

### Setting Up Groups

Currently, there are no default groups set up when you first install Ion. In order to grant yourself administrative privileges, you must be a member of the `admin_all` group.

To create and add yourself to the global administrator group, run the following commands:

```python
$ ./manage.py shell_plus
Python 3.5.2 (default, Nov 23 2017, 16:37:01) 
Type 'copyright', 'credits' or 'license' for more information
IPython 6.2.1 -- An enhanced Interactive Python. Type '?' for help.
>>> user = User.objects.get_or_create(username="YOURUSERNAME")[0]
>>> group = Group.objects.get_or_create(name="admin_all")[0]
>>> user.groups.add(group)
>>> user.is_superuser = True
>>> user.save()
```

### Connecting and Disconnecting from the VM

When you want to close the VM environment, make sure you have exited out of the ssh session and then run `vagrant suspend`. To resume the session, run `vagrant resume`. Suspending and resuming is significantly faster than halting and starting, and also dumps the contents of the machine’s RAM to disk.

### Setting up Files

You can find a list of file systems at `intranet/apps/files/models.py`. To add these systems so that they appear on the Files page, run the statements found in the file. A sample is shown below:

```python
$ ./manage.py shell_plus
Python 3.5.2 (default, Nov 23 2017, 16:37:01) 
Type 'copyright', 'credits' or 'license' for more information
IPython 6.2.1 -- An enhanced Interactive Python. Type '?' for help.
>>> Host.objects.create(name="Computer Systems Lab", code="csl", address="remote.tjhsst.edu", linux=True)
```

### Increasing RAM

With any RAM lower than the default 2048MB, you may run into performance constraints. If you encounter signifigant issues, it is recommended to bump the VM’s amount of memory, through VirtualBox Manager, to at least that amount.

## Reasons for Vagrant Setup

The Ion developers decided to use Vagrant to manage Ion's development environment because it closely modeled Ion's production server. Vagrant also enables the quick creation of VMs with various customizations possible.


# Environment

Now that you have set up your development environment, you should get familiar with your environment and the Ion code base.

## Useful Commands

### Vagrant

To manage your Vagrant box, you should use the following commands:

| Command | Description |
| ------- | ----------- |

| `vagrant suspend` | Saves the state of the VM |
| ----------------- | ------------------------- |

| `vagrant resume` | Resumes the previous state of theVM |
| ---------------- | ----------------------------------- |

| `vagrant ssh` | SSHs into the VM |
| ------------- | ---------------- |

| `vagrant reload` | Halts the VM and then brings it back up |
| ---------------- | --------------------------------------- |

| `vagrant up` | Brings up the VM according to specified `Vagrantfile` |
| ------------ | ----------------------------------------------------- |

| `vagrant destroy` | <p>(A DANGEROUS COMMAND)</p><p>Stops the VM & permanently destroys the VM and its contents</p> |
| ----------------- | ---------------------------------------------------------------------------------------------- |

To manage the Vagrant box within the box, you should use the following commands:

| Command                     | Description                           |
| --------------------------- | ------------------------------------- |
| `workon ion`                | Initialize virtualenvwrapper          |
| `fab runserver`             | Run a server in development           |
| `./manage.py migrate`       | Migrate the database if not already   |
| `./manage.py shell_plus`    | Enter a Python shell                  |
| `./manage.py collectstatic` | Collect static files into a directory |

You should ALWAYS make sure `workon ion` has been run after SSH-ing into the VM. The database should be migrated fairly regularly (especially after changes in the database/models) in development.

Running `fab runserver` should make the server accessible from `localhost:8080` (on your host machine's web browser).

Running `./setup.py test` should test your current code base against the Ion test suite.

## Code base

## Overall Structure

### Root

The root of the Ion git repository is split into many parts in order to allow developers to access information quickly:

* `config`:  Contains scripts/files used provision the Vagrant box
* `cron`: Contains cron bash scripts that are only run on production
* `docs`: Contains old Ion docs
* `intranet`: Contains most of Ion's code
* `Ion.egg-info`: Contains information about the Python Ion eggs
* `migrations`: Skeleton directory only created for migrations
* `scripts`: Contains scripts useful for Ion developers

Some useful files in the root of the Ion git repository include:

* `COPYING`: Contains the GPLv2+ for the Ion code
* `fabfile.py`: Describes behavior of `fab`.  Used for development/deployment.
* `manage.py`:  Contains wrapper for Django shell management commands
* `README.rst`: Contains the README
* `requirements.txt`: Contains Ion's dependencies
* `setup.py`: Describes the Python Ion package
* `Vagrantfile`: Describes configuration of the Vagrant box

## Intranet

Some useful sub directories of the `intranet` directory include (as per Django best practices):

* `apps`: Contains the vast majority of Django apps
* `middleware`: Contains Django middleware
* `settings`: Contains Django settings for Ion
* `static`: Contains CSS, images, JS, SVGs, themes, and useful documents
* `templates`: Contains Django templates and email templates
* `test`: Contains the Ion base test suite
* `utils`: Contains side-wide utilities

All other files in this directory are per Django convention. If you do not know what they do, Google it.

Within the `apps` directory, there are multiple Django apps with descriptive names.


# Fixtures

Fixtures are SQL queries that use a real production data set to populate the development database.  Since this contains personal information, access should be restricted.  Fixtures may be obtained (through a secure method) from an Ion admin if you are developing for Ion.

## Import

Once you get a zipped fixtures file, unzip the file to a `fixtures` directory in your main work directory.  Within the main work directory, run `./scripts/import_fixtures.sh` to import the fixtures.  This process may take some time.

## Export

To export fixtures from production, you should SSH to root on `ion`.  Navigate to the main directory, make a directory called `fixtures`, and run `./scripts/export_fixtures.sh`.  Your fixtures should be populated in the `fixtures` directory and can now be zipped for transfer.


# PR Workflow

## Prerequisites

Knowledge of Git is good to have for Ion development given that we store code in Git and use GitHub. Note that the most up to date version of this guide will be at <https://tjcsl.github.io/ion/developing/contributing.html>.

## Branching

Production code is stored on the `master` branch in the [Ion repo on GitHub](https://github.com/tjcsl/ion). The `dev` branch stores code used for testing before deploying to production.

Non-Ion maintainers should develop on their own forks of the main GitHub repository. You can read about it [here](https://help.github.com/articles/fork-a-repo/).&#x20;

## Preparation

When you think your code is ready to reviewed, it is important to ensure your changes comply with the Ion code guidelines. Here are some general guidelines

* First, you should review your code for compliance with the [Ion Style Guide](/services/ion/development/style-guide). &#x20;
* Second, you should make sure that only changes you wanted to make exist in your branch.
* Third, you should make sure your code will pass the build by running `./deploy` in the root directory. This will run tests, update `Ion.egg-info` and build the docs. At the end, you will probably get a message saying there are uncommitted changes. **This is fine**. As long as the script ends with an uncommitted changes message, you are ready to commit your code.

{% hint style="info" %}
In order to merge into master, it is recommended to write tests for any new code. If there is missing testing code, you should also write tests. To see some examples, look for `test.py` files in each app. More information can be found in the [Django docs](https://docs.djangoproject.com/en/dev/topics/testing/overview/).
{% endhint %}

* Fourth, commit your changes and write a simple and *descriptive* commit message.  Messages like `fixes` are **NOT** descriptive.

## Scope

The scope of your PR should be limited.

You should not make PRs changing various unrelated portions of the code.  For example, a PR focused on adding a new feature to printing should not be removing a test case for user authentication  (although you are free to open a separate PR for that).  In addition, you should not fix failed CI tests in the same PR (unless your code was the source of the errors).

## Opening a PR

After pushing your proposed changes to your own personal fork, it is time for you to open a PR.

* Head over to your fork and navigate to your branch via the drop down menu.  At the top of your code, you should see a button called "Pull request".  After you click it, you should see the opening of PR page.
* On this page, ensure your head fork is set to the branch with your changes, while the base fork is set to the Ion repository's `dev` branch.

{% hint style="warning" %}
The *only* people should open PRs with the `master` branch as the base branch should be individuals with push access to at least the *dev* branch.  These PRs against against the master branch should use the `dev` branch as the head fork.
{% endhint %}

* You must see a green check mark indicating that branch is able to merge.  If it is not, you should rebase and make the branch mergeable before proceeding.
* Write an informative title and describe your changes briefly in the description box.
  * Your changes should describe why you are changing something, how you are changing something, and what you are changing. &#x20;
  * A good, informative PR description helps the maintainers review your changes faster.
* Make sure only the changes you want to make are described in the PR.
* Submit it!

## Responding to Reviews

After your PR has been submitted, an Ion maintainer will review your PR.  They can take three courses of action after reviewing:

* approving the PR
* closing the PR
* or requesting changes to the PR

If your PR has been approved, there is no need to take any further action unless requested to.  The maintainer may wait for other maintainers to review your the code or may immediately merge the PR.

If the PR has been closed, the reason is generally described by the closing maintainer. &#x20;

If a maintainer has requested changes, you should correct your code per the recommendations and push additional commits to your head branch (or just rebase your branch). &#x20;


# Style Guide

The Ion code base generally follows the guidelines as set forth by [PEP8](https://www.python.org/dev/peps/pep-0008/).

## Main Points

* Indent using 4 spaces.
* Use underscores in favor of camel case for all names except the names of classes.
* Limit all lines to a maximum of 79 characters.
* Limit the line length of docstrings or comments to 72 characters.
* Separate top-level functions and class definitions with two blank lines.
* Separate method definitions inside a class with a single blank line.
* Use two spaces before inline comment and one space between the pound sign and comment/
* Use a plugin for your text editor to check for/remind you of PEP8 conventions.
* Capitalize and punctuate comments and git commit messages properly.

## Imports

* Group imports in the following order:
  1. Standard library imports
  2. Imports from core Django
  3. Related third-party imports
  4. Local application or library specific imports, imports from Django apps
* Avoid using `import *`
* Explicitly import each module used

#### Examples

Standard library imports:

```
from math import sqrt
from os.path import abspath
```

Core Django imports:

```
from django.db import models
```

Third-party app imports

```
from django_extensions.db.models import TimeStampedModel
```

Imports from your apps

```
from intranet.models import User
```

Explicit relative imports:

Used to avoid hardcoding a module's package. This greatly improves portability. Use these when importing from another module in the current app.

Absolute imports:

Used when importing outside the current app.

Implicit relative imports:

Don't use these. Using them makes it very difficult to change the name of the app, reducing portability.

Good:

```
from .models import SomeModel  # explicit relative import
from  otherdjangoapp.models import OtherModel  # absolute import
```

Bad:

```
from currentapp.models import MyModel  # implicit relative import
```

### References

* [Google Python Style Guide](https://google.github.io/styleguide/pyguide.html).
* [Google HTML/CSS Style Guide](https://google.github.io/styleguide/htmlcssguide.xml).
* [Google Javascript Style Guide](https://google.github.io/styleguide/javascriptguide.xml).
* [PEP8 Official Python Style Guide](https://www.python.org/dev/peps/pep-0008/).


# Maintainer Workflow

Maintainers of the Ion repository are responsible for the effective functioning of Ion.  Generally, the Ion maintainers are the Ion leads for the years plus other senior Ion developers if applicable. &#x20;

## Responsibilities

Ion maintainers need to ensure that the code base remains good quality and nothing will break.

Maintainers have the following responsibilities:

* Triaging issues (labeling, closing issues as appropriate)
* Reviewing pull requests
* Maintaining our CI pipeline (run via Travis)
* Ensuring the CI pipeline does not fail&#x20;
* Ensuring the code's compliance with the Ion Style Guide
* Protecting Ion from security threats
* Redacting private information from the Git repository
* Determining the best course of action to take (being the final arbiters of decisions affecting Ion)

## Issues

We have a system of labeling issues that are opened in the Ion repository.  Examples of labels that we have include:

* Browser compat
* Bug
* Cache
* Client-side
* Docs
* Enhancement
* Feature
* Feedback
* Help Wanted
* Invalid
* Question
* Server-side
* Vagrant
* Upstream
* Wontfix

Issues out of the repository's scope should be closed.  Duplicates of other issues should also be closed.  Maintainers should however be respectful of people who open issues.

## Pull Requests

Determining what code should be included in the Ion repository is a decision that lies ultimately with the Ion Lead.  Together, with the Lead Sysadmins and the Faculty Sponsor, they serve as the FINAL decision makers on what to include or remove from Ion.

Pull requests should be reviewed fairly regularly so that contributors can respond to the feedback that is given by the reviewers.  The process for determining who should authorize/approve merges into the `dev` and `master` branches is to be determined each year by the Ion Lead.

## Evaluating Pull Requests

When evaluating pull requests, maintainers look at various factors including:

> * Correctness: Does the code do what it claims to do? Is the code correct in both the nominal case and the boundary cases? As a reviewer, this is your opportunity to point out edge conditions of which the original developer may not have been aware.
> * Complexity: Does the code accomplish its task in a reasonably straightforward way? If you can point out simpler approaches that do not compromise the correctness or performance of the code, you should.
> * Consistency: Does the code achieve its basic goals in a way that is consistent with how similar code in our codebase achieves those goals? Is it re-using the available libraries and utility classes? Where possible, has code been refactored for re-use instead of just copying and pasting?
> * Maintainability: Could the code be extended by another developer on the team with a reasonable amount of effort? More than any item on the list, this is the karma investment you make by doing code reviews - the code you review today may be the code you have to update tomorrow, so taking the time to make sure it’s maintainable by others pays itself back to you.
> * Scalability: Will the code be performant at the expected volumes? It is important that this question always be asked in the context of expected volumes. When building a new product in an untested market, it is fine to write code that works for 10,000 users but not 1M; if the product should be that successful, we will profile, optimize, and, when necessary, re-write the critical bits. The corollary is that we should not spend time optimizing code when the market demand is unproven.
> * Style: Does the code match the team style guide? This should rarely be controversial.
>
> Adapted from <http://engblog.yext.com/post/effective-code-reviews>

PRs that add new features **should** include unit tests that cover all added code.

&#x20;


# Repository Maintenance

#### Branches

We maintain two principal branches:

* `master`: hosts the code for production; should be production-ready
* `dev`: hosts the code in preparation for merge to `master`

Feature branches can be created by any committer to host their feature or bugfix branch.

Once a branch has gone three months without activity or it has been merged into the principal branches, it should be deleted and consider "stale".


# Data Generation

## Generating Users and Eighth Periods

Once you have your Vagrant environment set up, log into [GitLab](https://gitlab.tjhsst.edu/). If you do not have access to GitLab, email sysadmins\@tjhsst to request access.

After you log in, clone the Ion Fake Data repo [here](https://gitlab.tjhsst.edu/sysadmins/web/ion/ion-fake-data). Follow the instructions in `README.md` to generate JSON files for importing user and eighth period activity data.

Move the JSON files into the main directory of your local intranet copy, and ssh into your Vagrant machine. Then run `python manage.py import_users user_import.json` and `python manage.py import_eighth eighth_import.json` to import user and eighth period activities.

In order to show eighth period activities on Ion, you need to create eighth period blocks. Run `python manage.py dev_create_blocks mm/dd/yyyy` and fill in an end date. This script will create blocks every Wednesday and Friday from the current date until the end date.

Once blocks have been created, you can generate signups for the blocks on a specific date by running `python manage.py dev_generate_signups mm/dd/yyyy` by inputting a specific date which has eighth period blocks. The commands to generate blocks and signups for testing should ONLY be used in your local version of Ion.

Now you have enough data to begin testing changes on users and eighth periods.


# Production

Steps to install Ion are described in our Ansible playbooks.

Information on how to run Ion in production is located in [our runbooks](/general/documentation/runbooks). (Note that this information is closed to people with explicit permission only.)

## Troubleshooting tips

1. A 502 Bad Gateway ("Unable to contact an application server") indicates a problem with Daphne.
2. If you can access static files (like <https://ion.tjhsst.edu/static/css/base.css>) with no problem, but dynamic pages like the login page give errors or are very slow to load, it's almost definitely a problem with either Daphne or the database. (Conversely, if static files exhibit the same problem, it's probably an Nginx issue.)
   1. You might be able to resolve Daphne issues by increasing the number of workers. Just make sure that 1) you add them to the Nginx config and 2) you increase the PostgreSQL connection limit appropriately (you'll want to run `systemctl restart postgresql && supervisorctl reread && supervisorctl update && systemctl restart nginx`when you've edited all the config files).\
      Each Daphne worker seems to require about 75 connections, and you'll want a buffer over that.
3. If Ion is experiencing performance issues, try these troubleshooting steps:
   1. Try and access a static file (see #2 above).
   2. SSH to Ion and run `iotop`. If you see high disk usage, database access might be the slowdown.


# User Experience


# User Interface

The user interface should be consistent and should not drastically impact the use experience.


# Director

The Director website management platform

**Director 4.0** is a website management interface for student and activity websites. It was created during the 2019-20 school year and is currently used by many of the web application development classes.

The application was created to provide a secure, beginner friendly, and highly customizable website hosting platform. To achieve this goal, many features, including a web terminal and online editor, were implemented. The project has been completely [student-built](https://director.tjhsst.edu/about), and was the senior research project of Class of 2020 Sysadmins. Director 4.0 was the next iteration of web3, the senior research project of Eric Wang (class of 2017).

See what's new in Director 4.0 [here](https://director.tjhsst.edu/docs/whatsnew-director4/).

The point of contact for Director is [the Director Lead.](/general/sysadmins-list#current-leads)

## Technologies Used

* Python
* Django
* Docker

## External Links

* [Director](https://director.tjhsst.edu/)
* [Director Guide](https://director.tjhsst.edu/docs/)
* [Director on GitHub](https://github.com/tjcsl/director)


# Development


# Vagrant Setup

Director Development using Vagrant

## Getting Started

Similar to Ion, Director has a setup using Vagrant. This page will go over about setting up for Director using Vagrant. Refer to the Github page for setting up a developer environment for more up to date information.

First off, install [VirtualBox](https://www.virtualbox.org/wiki/Downloads) and [Vagrant](https://www.vagrantup.com/downloads), VirtualBox is a virtualization program, and Vagrant is the development environment in where we'll run Director. For more information about those two services, please take a look at their documentation linked below.

If it is not installed already, install [Git](https://git-scm.com/). Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency. This is essential for Director if you are going to be pushing changes to it.

Ensure you have an SSH key set up with GitHub by running `ssh -T git@github.com`. You should be greeted by your username. If not, set up an SSH key with GitHub by following [these instructions](https://help.github.com/articles/generating-an-ssh-key/).

Clone the Director 4.0 repository onto your computer and `cd` into the new directory. Essentially just run `git clone git@github.com:tjcsl/director4.git director && cd director`.

{% hint style="info" %}
Note: if your host machine is running Windows, please run `git config core.autocrlf input` before cloning to prevent line ending issues.
{% endhint %}

```bash
$ git clone git@github.com:tjcsl/director4.git director
$ cd director
```

Once inside the `director` directory, run `vagrant plugin install vagrant-vbguest`. If you are on Windows, also run `vagrant plugin install vagrant-winnfsd`.

Run `vagrant up && vagrant reload` and wait while the development environment is set up. This will download a Vagrant image and provision the resulting VM.

## Post-Setup

After successfully setting up the Vagrant environment, you will want to actually access your sandbox.

Start by connecting to the Vagrant box using `vagrant ssh` to connect to the VM.

Once inside, run `cd director` to change into the repo and `./scripts/install_dependencies.sh` to install Director's Python dependencies using `pipenv`.

Once completed, you may now work on Director `scripts/start-servers.sh` will open a `tmux` session with the four servers each running in a separate pane.

* Note: If you are not familiar with `tmux`, we recommend <https://www.hamvocke.com/blog/a-quick-and-easy-guide-to-tmux/> and <https://tmuxcheatsheet.com/> as starting resources.
* See [this](https://github.com/tjcsl/director4/blob/master/docs/docs/tmux.md) for an explanation of the components of the development `tmux`

When you are finished, type `exit` to exit the VM and `vagrant halt` to stop it. When you want to work on Director 4.0 again, `cd` into this directory, run `vagrant up` and `vagrant ssh` to launch the VM and connect to it, and then run `exit` and `vagrant halt` to exit and shut it down.

## Documentation

* VirtualBox - <https://www.virtualbox.org/manual/UserManual.html>
* Vagrant - <https://www.vagrantup.com/docs>
* Git - <https://git-scm.com/docs>


# PR Workflow

Follows Ion's [PR workflow](/services/ion/development/pr-workflow)


# Style Guide

Follows Ion's [style guide](/services/ion/development/style-guide)


# Maintainer Workflow

Maintainers of the Director repository have the same responsibilities as outlined in Ion's [maintainer workflow](/services/ion/development/maintainer-workflow)


# Production

Information on production Director is located in [our runbooks](/general/documentation/runbooks).


# Workstations

CSL desktop workstations

In the CSL, **workstations** are a group of computers that are maintained by the Sysadmins to provide TJ students and staff a Linux environment. Currently there are over 60 **HP Z240 Tower Workstations** that are located in rooms 200 and 202. These workstations are often used by computer science classes which includes Computer Vision and Artificial Intelligence. Seniors, who are enrolled in doing research for the Syslab or Web/Mobile App Development, often use our workstations as well.

## Technical Specifications

Most workstations have **similar** specifications listed below:

| Specification | Description                             |
| ------------- | --------------------------------------- |
| Motherboard   | HP 802F                                 |
| CPU           | Intel(R) Core(TM) i7-8700 CPU @ 3.40GHz |
| RAM           | 1-2x Hynix 8GB DDR4-2133                |
| GPU           | NVIDIA Quadro K620                      |
| Hard Disks    | 1 Terabyte HDD                          |
| OS            | Debian 13                               |

## The Pit Workstations

<figure><img src="https://3496721629-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LKalf7rYxXVbB0kIEA2%2Fuploads%2FHe36kkstwQJJfyDAasDU%2FPXL_20230615_154220614.jpg?alt=media&amp;token=4b7f7b6b-a66e-4e68-b59c-e7fc97e64aef" alt=""><figcaption><p>The Pit - June 2023</p></figcaption></figure>

**The Pit Workstations** are workstations located in the Pit that are mainly intended for Sysadmin use. Some of the workstations below don't have the same specifications that are listed above.

* **`mozart`** - Runs Ubuntu 22.04, has the same specifications as other workstations.
* **`turing`** - Runs Debian 12, has the same specifications as other workstations.

## Room 200

Almost half of our workstations are located in Rm 200. These workstations are used mainly for AI and senior research.

* `eevee`
* `meowth`
* `psyduck`
* `growlithe`
* `machop`
* `geodude`
* `slowpoke`
* `bulbasaur`
* `ivysaur`
* `venusaur`
* `charmander`
* `charmeleon`
* `charizard`
* `squirtle`
* `wartortle`
* `blastoise`
* `caterpie`
* `metapod`
* `butterfree`
* `pikachu`
* `gastly`
* `beedrill`
* `pidgey`
* `snorlax`
* `onix`
* `cubone`
* `lapras`

## Room 202 <a href="#id-202" id="id-202"></a>

The other half of our workstations are located in Room 202. These workstations can be accessed remotely through Guacamole, or used over ssh / in-person.

* `prokofiev`
* `hindemith`
* `puccini`
* `rachmaninoff`
* `wagner`
* `vivaldi`
* `stravinsky`
* `schumann`
* `handel`
* `gershwin`
* `faure`
* `debussy`
* `copland`
* `chopin`
* `brahms`
* `bernstein`
* `satie`
* `ravel`
* `scarlatti`
* `schubert`
* `berlioz`
* `bach`
* `haydn`
* `tchaikovsky`
* `mendelssohn`
* `pachelbel`
* `mahler`
* `vecchio`
* `holst`
* `liszt`

## Accessing the Workstations

Accessing is fairly simple when it comes to workstations. If you're on VPN, just running `ssh <WORKSTATION_NAME>.csl.tjhsst.edu` (running `ssh <WORKSTATION_NAME>` should also work as well) should do the trick, however if your not on VPN, there are a few steps:

{% hint style="info" %}
Note that you should always check if the workstation is SSHable in the first place, by simply checking if it is pingable by running `ping <WORKSTATION_NAME>`. If it is not pingable, then it is likely off or broken. Ask the Workstations Lead(s) if you have questions.
{% endhint %}

1. Open the terminal and run `ssh <YOUR_ION_USERNAME>.remote.tjhsst.edu`. This is our remote access servers, which allows you to access any CSL-related items outside of TJ. This should open a prompt that would asks you to type in your password.
2. Once your in, you should just SSH into the workstation as so: `ssh <WORKSTATION_NAME>`.

For more specific information on CSL workstations are located in [our runbooks](/general/documentation/runbooks).

Note that some workstations are being used for other purposes and may not be accessible.


# Signage

The CSL Signage displays

**Signage** refers to the set of ten electronic displays located all over the school. A "Signage" refers to a display that displays useful information maintained by the CSL across the school.

All signages (except for `cs-audlob`) have the same types of features which include:

* The schedule of the current school day.
* Ion announcements
* 8th period activities.
* A bus map
* A map of the whole school.

Signages can also showcase important announcements made by the Sysadmins or FCPS.

The current version of Signage is **Signage3**.

The core of Signage runs on Intel Compute Sticks ([official website](https://www.intel.com/content/www/us/en/products/boards-kits/compute-stick.html)) running Ubuntu 16.04 LTS.

The main contact for signages are our Signage Lead(s). The Intranet Lead(s) are usually the deputies for signages if the Signage Lead(s) are not present.

## History

### Signage1

The first Signage displays were installed around the first release of Ion ([source](https://tjhsst.edu/~jwoglom/ion.pdf)) (around May 2016). They were originally developed as a complement to Ion. These efforts were led by James Woglom. The Signage displays ran on a mixture of Raspberry Pi 1s, Raspberry Pi 2s, and Raspberry Pi 3s.

![](https://3496721629-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LKalf7rYxXVbB0kIEA2%2F-LLS90aJVn69Kps-Gfq3%2F-LLS8ubkuQrK74gRD89c%2Fsignage1.png?alt=media\&token=97e5c283-3884-4a79-8d7a-8fad8fd421b2)

### Signage2

Development of Signage2 began in April of 2017 to serve as a rewrite of Signage1 using Python's Kivy framework. Various limitations imposed by Kivy and slow performance led to the end of development around March of 2018.

### Signage 3

Development of Signage3 began in March of 2018 to serve as a rewrite of Signage as a webpage hosted on Ion. Signage3 was deployed on newly-arrived Intel Compute Sticks on April 12, 2018. Signage3 remains the current Signage deployed throughout the school.

## List

The current deployed Signage displays are named (and located):

* `cs-nobel` (Nobel commons)
* `cs-curie` (Curie commons)
* `cs-galileo` (Galileo commons)
* `cs-cafeteria` (Cafeteria)
* `cs-gandhi-a` (Ghandi commons)
* `cs-audlob` (Outside the audlob)
* `cs-library` (Library hallway)
* `cs-hopper` (Hopper commons)
* `cs-cafe` (Cafe commons)
* `cs-einstein-a` (Einstein commons)

## Current Setup

Each Signage display has their own Intel Compute Stick which runs Ubuntu Server 20.04 LTS. Using getty, each Signage display logs in as `user` and opens up a specific web page on Ion (`https://ion.tjhsst.edu/signage/display/<display_name>`) in Chromium. The Signage pages can be rendered server-side or as iframes. The code for Signage can be found [here](https://github.com/tjcsl/ion/tree/master/intranet/apps/signage).


# Setup

## Network Configuration Overview

Each Signage Intel Compute Stick connects to TJ's Windows network. Each stick's MAC address is whitelisted by TJ's Tech Team to access the `tjhsst` network. Using [wpa\_supplicant](https://wiki.archlinux.org/index.php/WPA_supplicant) and [systemd-networkd](https://wiki.archlinux.org/index.php/Systemd-networkd), each stick is assigned an IP on the Windows network.

## Installation

In the past, Signage was a separate web application from Ion, viewed on Raspberry Pis.

Now, Signage is run on Intel Compute Sticks running Ubuntu Server with a minimal GUI.

This guide will show you how to set up a new stick.

### Manual Stuff

#### Installing the OS

When you first get one of the [Compute Sticks](https://livedoc.tjhsst.edu/wiki/Compute_Sticks), it should come pre-loaded with Windows 10 by default. If this is not the case, you probably got the wrong version of Compute Stick (the Ubuntu ones aren't powerful enough).

**Prepare the Installation USBs**

These steps only have to be done if there are no installation USBs around.

*This guide assumes (hopefully correctly) that you know how to manage USBs on whatever computer you are using.*

1. Download the OS.
   * Head on over to Ubuntu's [website](https://ubuntu.com/download/server) and download the  `.iso` for the the latest LTS version.
2. Put the OS on a USB.
   * On Linux or Mac, use the `dd` utility to flash a USB with the OS installer. On Windows, use [Win32DiskImager](https://sourceforge.net/projects/win32diskimager/::) or something to that nature.
   * Example `dd` command: `sudo dd if=ubuntu_server-16.04.iso of=/dev/sdx progress=status`, replacing `sdx` with the actual USB device identifier.
3. Download the `wpa_supplicant` package and dependencies.
   * On an Ubuntu system with the same architecture as the Compute Stick (preferably an existing Compute Stick), use this command to download `wpa_supplicant` and all of its dependencies:

     ```
     apt-get download wpa_supplicant && apt-cache depends -i wpa_supplicant | awk '/Depends:/ {print $2}' | xargs apt-get download
     ```
   * On a Windows or Mac system, you will have to do this manually by tracing dependencies.

**Get Configuration Files**

There is a GitLab [repo](https://gitlab.tjhsst.edu/signage3/cs-config) which contains important scripts and config files to setup networking and an Ansible-ready system.

You should clone it by running within the mounted wpa\_supplicant drive

```
git clone git@gitlab.tjhsst.edu:signage3/cs-config.git
```

**Boot from the OS Install Disk**

1. Plug in a keyboard into the Compute Stick.
2. Plug the Stick into an available monitor.
3. Turn the Stick on.
4. As the Stick is booting, repeatedly press the F10 key until you see a boot menu.
   * If this does not work, reboot and try again.
5. At the boot screen, select the USB as the boot device.
   * If you can't boot, [Google](https://google.com) what went wrong.
6. Follow the on-screen prompts to install Ubuntu Server LTS.
   * Try to install as few extra features as possible.
   * Set the username/password as instructed by the Signage Lead. The password, however, will be changed later.

**Mount the USB**

Now, plug in the other installation USB (the one with the packages on it) into the Compute Stick. Mount it with

```
sudo mount /dev/sdxn /mnt
```

where `sdxn` is the USB partition you stored the files on. `x` will usually be `a`, and `n` will usually be `1`.

### Automatic Configuration

Scripts to complete initial setup of the script can be found on [GitLab](https://gitlab.tjhsst.edu/signage3/cs-config). You will need to copy this repository to a flash drive.

* Cd into `/mnt/cs-config`.
* Run `./setup_network.sh <LAST TWO DIGITS OF IP>` to configure networking.
* Reboot.
* Check that you have internet (`ping`) and use `ip a` to check that you have been assigned an IP address.
* Run `./setup_finish.sh` to complete setup (install python basic config).
* From your device, run the CSL Ansible play for signage (`signage.yml`) to configure the base of the system.


# Administration

## Sign/Page Administration

### Develop New Page

Views for each Signage page are located in the [pages.py code](https://github.com/tjcsl/ion/blob/master/intranet/apps/signage/pages.py). To add a new page, define the context in `pages.py`. The template should be defined in `templates/signage/pages/<page_name>.html`.

### Create New Page

Each Signage display renders multiple pages. Each page is defined within a `Page` model. Within Django admin, define the:

* name: Some descriptive name to represent the Page (required)
* template: The location of the template (`templates/signage/pages/<template>.html`)
* function: The function defined in `pages.py` for server-side rendering of context (e.g. `hello_world`)
* button: The name of the font-awesome icon to be used on the navigation bar (e.g. `fa-bus`)

The other fields can be left at their defaults.

Example:

![Example Page](https://3496721629-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LKalf7rYxXVbB0kIEA2%2F-LLu9nDwRF_VLfOFoMCT%2F-LLu9_QEaD2obQQ8DyDz%2Fsignage2.png?alt=media\&token=5b641a03-a357-4cd6-a705-0d10aa68912d)

The example Page shown above is named `Announcements`.

* Since we want the page to be rendered server-side (not as an iframe), the `iframe` box is not checked.&#x20;
* Since the page is not an iframe, we leave the `url` field as is.
* Since the page is not an iframe, we can leave the `sandbox` checkbox as is (for more information about sandboxes read <https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-sandbox>).
* The `template` field is set to `announcements`, meaning that Ion will try to render `templates/signage/pages/announcements.html`. &#x20;
* The `function` field is set to `announcements`, meaning that Ion will use the `announcements` function in `pages.py` as context.
* The `button` field is set to `fa-newspaper-o`, meaning that this Font Awesome icon will be used in the navigation bar. &#x20;
* The `order` field is set to 1, meaning that the button is second on the navigation bar.  The pages should be ordered as you want them to appear on the bar (required).
* The `strip_links` field is checked off because you should not be able to navigate off a page by clicking a link.  If this functionality is not desired, uncheck the box.

### Create New Sign

Each Sign is defined within a `Sign` model. Within Django admin, define the:

* `name`: Some friendly display name (required)
  * This is displayed on the main schedule page (e.g. Curie Commons)
* `display`: A unique name (the Stick's host name) (required) (e.g. cs-curie)
* `landscape`: True if display is landscape (bar on right-hand side) and False if display is not landscape (bar on the bottom of the screen)
* `map_location`: This field is not used
* `img_path`: A URL to an image to display on the main schedule page.  Leave at the default for the default TJ image (required)
* `lock_page`: A `Page` that should be the only page displayed (if not set all pages will be displayed)
* `pages`: A `ManyToManyField` containing all pages to be rendered on the Sign (required)
* `default_page`: A `Page` that will be reverted to after a period of time

Example:

![](https://3496721629-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LKalf7rYxXVbB0kIEA2%2F-LLu9nDwRF_VLfOFoMCT%2F-LLu9qkuFP7TZ7n_5BZe%2Fsignage3.png?alt=media\&token=ddaa8886-ba8a-4102-971a-7b468b8e175e)

The example Sign shown above is named `Curie Commons` (and should be deployed there):

* Since it is deployed in Curie Commons, we should set `name` to that.  This is also what appears on the Signage display as the display name.
* The `display` field is set to cs-curie because that is the host name of Sign. &#x20;
* The `eighth_block_increment` field can be left as is because this field was only used in Signage1.
* The `img_path` field is set to the default image path in order to render  the default image of the front school.  Appropriate images should be selected for each sign (generally a picture of the scientist for whom the commons is named for).
* The `lock_page` field is left as is, meaning that all pages are displayed.  For specific Signs, a lock\_page may need to be specified.
* The `default_page` field is left as is, meaning that the default first page when loaded is the schedule page.  In some cases, a specific page should be displayed on a Sign.  For example, the bus depot display (`cs-audlob`) needs to display the bus map by default.
* All pages that should be rendered by the Sign should be selected in the `pages` field.  They are ordered as per their specified order.

### Special Events

Signage is often used to display pages for special events that occur at TJ. Generally, these are just iframes to some outside webpage. A specific Page should be made for an event. The `iframe` box should be checked off and a link to the page should be set in the `url` field. The `template` and `function` fields do not need to be filled out in such case.

## Display Administration

### Rebooting

Often it is necessary to reboot Signage displays. To perform a reboot manually, run `sudo shutdown -r now` or `sudo reboot` within the Signage's terminal. To reboot the entire deployment, run `ansible -i hosts -a "shutdown -r now" -u user -K signage`.

### Connecting

To SSH to the Signage displays, a CSL VPN is necessary. Ask a VPN admin to set up a certificate for you.

To SSH without the Signage password, you should add your RSA public key to the `public_keys` folder in the Ansible repo. Then, you should add the path to that public key to `roles/signage/tasks/main.yml` under `Update authorized_keys`. After that a Signage admin (or you, if you have access to the `signagepi` passcard) should run the playbook.

### Running Ansible

It is a very good idea to keep all changes for the Signage deployment in sync through Ansible. Run `ansible-playbook -K signage.yml` to propogate changes from the Signage playbook to the deployment.


# Monitoring

## Grafana

A [Grafana dashboard](https://grafana.tjhsst.edu/d/9P-CqBmZz/signage?orgId=1) (only accessible via a CSL VPN) offers a comprehensive overview of all of the signages in the school. The dashboard posts alerts to `#signage` when displays malfunction.

## signage-exporter

The Grafana dashboard is supported by a [prometheus backend](https://github.com/tjcsl/gitbook/tree/7024241bfb385d5310f2921f8312b5067aa08dfd/technologies/monitoring/grafana/README.md), which scrapes data from each individual display's `signage-exporter`. `signage-exporter` is stored in the [ansible](https://github.com/tjcsl/gitbook/tree/7024241bfb385d5310f2921f8312b5067aa08dfd/technologies/tools/ansible/README.md) repository under `roles/signage/files/signage-exporter.py`. It is run from i3config and detects the connected display and touch inputs.


# Troubleshooting

**There is no internet on** `cs-library`**. Help!**

`cs-library` has always had trouble with the Wi-fi in that area.  Hence, Ansible is not run on it and`unattended-upgrades` do not run on it.  It would be nice to have a network drop for a wired connection.

**Why can I not access Ion or it says "Access Restricted"?**

First, you should check that you have a network connection.  Second, you should make sure that the IPs of the Signage displays are within the `INTERNAL_IP` range defined in Ion's  production's `secret.py`.

#### A signage is not on, but its software is functional. What do I do??

First off, check the hardware of the signage. Some connections might be broken, or something might be unplugged (for some reason). If everything seems clear, it might be that the input of the monitor is wrong, and it needs to be changed. Just find the buttons on the monitor and change the input to HDMI.


# Experimental


# IonTap

**IonTap** was an experimental project to allow users to sign up for 8th period on the Signage displays. The project was led by Keegan Lanzillotta. Code for the prototype TapIn can be found on [GitHub](https://github.com/keegan/TapIn). The project would rely on issued NFC cards as identification and the touch Signage displays as kiosks.


# SignageAdmin

**SignageAdmin** was an experimental project to administer the Signage displays. It would use localized `mousescript2` installations to detect tampering of the Signage displays. Specifically, it would shut down Signage displays if unauthorized devices are connected or authorized devices are disconnected. (In the future, after experiments have been conducted on live Signage displays, the shutdown may be changed to a reboot.)

Signage Admin would also provide a web interface to administer the Signage displays, and possibly even notify sysadmins if anything happens to a Signage display, such as loss of networking or the connection of unauthorized devices. In addition, the web interface would provide an option to temporarily disable `mousescript2`, allowing sysadmins to connect a keyboard and/or mouse for system maintenance should it become necessary.

The project was led by John Beutner and Theo Ouzhinski.  The code, along with additional information such as setup instructions, can be found in the [signage3 namespace on GitLab](https://gitlab.tjhsst.edu/signage3).&#x20;


# Remote Access

The CSL's remote access servers

The CSL employs a remote access functionality called **Remote Access Servers** (RASes for short) for students and staff to access their CSL files outside school grounds. Currently, we have two remote access servers (`ras1` and `ras2`) which are both VMs that are the only machines beyond a select few that provide incoming SSH from outside the CSL network.

We use [fail2ban](https://github.com/fail2ban/fail2ban), an intrusion detection software, to block repeated mass authentication attempts against the remote access servers.

Issues related to the Remote Access Servers should be directed to the [Infrastructure Lead](/general/sysadmins-list#current-leads).


# Setup

## Installation

To setup a RAS server, it is necessary to create a VM server. Follow the instructions found in the QEMU pages of these docs to create a VM server. It should be on the 1802 VLAN with DHCP and DNS configured.

You should run the Ansible play `ras.yml` to create the base VM config, install/configure the OpenAFS client, install Python utilities, and configure fail2ban.

You should not have to take any other action than allowing SSH through the firewall, adding a DNS entry for the server, adding a DHCP entry for the server, and generating a keytab for the server.


# Administration

## IP Banning

fail2ban is sometimes a bit too aggressive.  After being fully banned, the ban lasts in the database for about 24 hours. &#x20;

fail2ban is a systemd service and can be restarted via the regular systemctl commands.

Run

```
iptables -L f2b-sshd
```

to retrieve a list of all banned IP addresses.  You can view a log of fail2ban activity at `/var/log/fail2ban.log`  .

To unban an IP, run

```
fail2ban-client set sshd unbanip <IP>
```

To ignore an IP until the next fail2ban restart, run

```
fail2ban-client set sshd addignoreip <IP>
```

To ignore an IP permanent, edit the ignoreip directive in the tjcsl.conf file within the `ras` role on Ansible.  You can then deploy the edited file via Ansible.

## Updating

{% hint style="warning" %}
Please keep in mind the CSL [upgrade guidelines](/policies/upgrade-policy) for production systems when deciding whether to upgrade RAS. When in doubt. ask someone more experienced and BACKUP DATA.
{% endhint %}

The remote access servers are like any other Ubuntu Server and can be upgraded via a regular `apt update && apt upgrade`.  It is recommended to upgrade the RAS servers via Ansible and to do so one at a time so that failed upgrades do not completely break access to the Lab.


# Cluster

The CSL's cluster. Note that this section is pretty old and may have outdated details.

## Purpose

The cluster was purchased by the Computer Systems Lab to serve the Parallel Computing and Computer Vision classes, but is available for usage by all TJ students and staff. Several senior research labs have expressed interest in using the cluster's resources for their own purposes. Academic jobs run on the cluster will receive priority allocation of resources, but non-academic jobs are accepted as well as long as they abide by the FCPS Acceptable Use Policy (Regulation 6410).

## Specifications

The CSL cluster (as of 2024) consists of 12 HPC cluster nodes, 40 Borg nodes, and 3 dedicated GPU nodes (snowy, unicron, zoidberg). This setup occupies almost 3 full racks in the server room. The Borg nodes are named borg\[1-40] consecutively, the HPC nodes are named hpc\[1-12] and the login node is `infoprism`.

### Uninterruptible Power Supplies (UPSes)

The HPC cluster rack currently has two UPSes, each with a maximum power capacity of 5000 Volt-Amps (Watts). The UPSes are APC brand, model number SRT5KRMXLT. They are online UPSes, which means they are continuously conditioning power, and there would be no delay in switching to battery if power were to fail, like with an offline UPS. One NEMA L6-30R 30A output from each UPS is connected to an APC PDU which runs on the side of the cluster rack. **The entire cluster rack operates at 240V, not 120V.**

### Top-of-rack Switch

(most likely out of date, change later)

One Juniper EX4300-48T-AFI 48-port Gigabit Ethernet switch, named [Imply](/machines/switches/imply), operates as a top-of-rack switch for the cluster nodes and for the UPSes. The switch is managed and runs JUNOS. It has one EX-UM-4X4SFP 4x10GigabitEthernet uplink module, which connects the switch to the CSL core switch, [Xnor](/machines/switches/xnor), over bonded, redundant 10GE fiber optic uplinks. The switch has one 350W power supply.

### Compute Units

Each compute unit is a 2U [Supermicro SuperServer 2027TR-HTRF](http://www.supermicro.com/products/system/2U/2027/SYS-2027TR-HTRF.cfm), with four hot-pluggable nodes, for a total of twelve logical compute nodes in the HPC cluster.

#### Power

Power is shared between the nodes in each unit. Each unit has two redundant 80 Plus Platinum 1620 Watt power supplies, which are connected to the *same UPS*. The reason for this is that if one of the UPSes were to fail or run out of power faster than the other UPS, one UPS (with a maximum power capacity of 5000 Watts) would not be able to sustain the entire cluster (with a maximum power capacity of approximately 6900 Watts) on its own. Therefore, the cluster units are distributed between the two UPSes, but are not redundant between the two.

#### Networking

Each node in each unit has independent networking. Each of the twelve nodes has two primary Gigabit Ethernet uplinks to the top-of-rack switch, as well as one uplink for the Supermicro Intelligent Platform Management Interface (IPMI) management port.

#### Processors and Memory

Each node in each unit has its own processors and memory. Each node has two Intel Xeon E5-2630v2 6-core 2.6GHz processors, for a total of 144 cores in the cluster. Each node also has 4x16GB Kingston DDR3 1600 ECC Registered memory units, for a total of 64GB of memory per node, for a total of 768GB of memory in the cluster.

#### Storage

Each node has its own storage, which may vary across nodes. Read about specifics in the [Machines ](/machines)section.

### GPU Node

The cluster also contains one 1U [SuperMicro SuperServer 1028GQ-TRT](http://www.supermicro.com/products/system/1u/1028/SYS-1028GQ-TRT.cfm) which functions as a node for GPU-intensive processing. It contains two NVIDIA Tesla K80 GPU Accelerators, each with two Kepler GK210 GPUs. Each GK210 GPU has 12GB of GDDR5 memory and 2496 CUDA cores, for a total of 48GB GDDR5 and 9982 CUDA cores.

Aside from the GPUs, it has two Intel Xeon E5-2620 v3 8-core 2.4GHz processors and 4xKingston ValueRAM 16GB DDR4 ECC Registered memory modules, for a total of 64GB RAM. For power, it has two redundant 80-Plus Platinum 2000W power supplies, and for networking it has two primary 10GbE uplinks to the top-of-rack switch (only operating at 1000Gbase-T) and one IPMI management port uplink to the top-of-rack switch.

## Configuration

The cluster's infrastructure is managed using the Ansible configuration management system. The Ansible plays are located in the [Ansible repository on GitLab](https://gitlab.tjhsst.edu/sysadmins/ansible), under the files `hpc.yml`, `hpcgpu.yml`, `ibm.yml`, `ibmgpu.yml`, and `clustermaster.yml`.

The [CephFS](/technologies/storage/ceph/cephfs) mount `/csl` contains user home directories, which are shared between cluster nodes, the login VM, and most workstations. Users are expected to use OnDemand or to login to infoprism (or the login VM) to run jobs using SLURM.

Speaking of SLURM (the Simple Linux Utility for Resource Management), Slurm is the utility used for job control and submission. Users log in to infosphere, run some simple commands, specifying what they want to run, how many resources it should have, priority, and other optional arguments, and SLURM takes care of allocating cluster resources for them, and provides job accounting so users know the status of their jobs. More information at our [Slurm docs](/services/cluster/slurm).


# FAQ

Because I'm tired of explaining the same things over and over again

## Using the Cluster

* How do I get my code on the cluster?
  1. From a [workstation](/services/workstations) with your code on it:

     ```bash
     scp -rp folder_with_your_code/ infoprism:~
     ```
  2. Your code is now on infoprism
  3. Hopefully your code should automatically sync between the workstations and cluster, but this is not always the case.
* Where do I go to run code on the cluster?
  * From [RAS](/services/remote-access) or a [workstation](/services/workstations):

    ```bash
    ssh infoprism
    ```
* How do I compile code on the cluster?
  * If using a single C/C++ file like a pleb:

    ```bash
    mpicc your_file.c # or mpicxx if using C++
    ```
  * If using CMake like a boss:

    ```bash
    cmake . -DCMAKE_C_COMPILER=mpicc -DCMAKE_CXX_COMPILER=mpicxx
    make
    ```
* Do I need to compile my code on the cluster?
  * **YES**, there is no other option, binaries will ***never*** be compatible. This is not a challenge, this is a statement of fact. Do not complain if your `a.out` from the workstation doesn't work.
* Now that I did all that, how do I run code on the cluster?
  * If using an MPI binary *(most parallel computing classes)*, or just running a non-MPI binary `n` number of times:

    ```bash
    srun -N <number_of_machines> -n <number_of_processes> --mpi=pmix_v2 ./your_binary --your-binary-flags
    ```
  * Alternative (non-preferred) method of running an MPI binary:

    ```bash
    salloc -N <number_of_machines> -n <number_of_processes> mpiexec ./your_binary --your-binary-flags
    ```
* That gives me some error about not having an account! What gives?
  * Ask a sysadmin if they can make you an account on the cluster. Point them to this document if they don't know how.
* My job just hangs forever!
  * Either someone is inconsiderately using the entire cluster, or the cluster is broken. If this is the case, please email us.
  * To check the former, use the `sinfo` and `squeue` commands.
* When I access the cluster, I'm not in my home directory, I'm in the root directory!
  * This is a problem with mounting, sometimes you just have to wait a bit.
  * In other cases, you might just not have a home directory because that machine is being used for something important.

## Managing the Cluster

Or, "I was put in charge of your mess Jack you better have documented everything." Don't worry, I didn't. Keeps you on your toes.

Note: everything here expects you have root access on infosphere, and are running all these commands as root.

* What are the basic troubleshooting steps?
  * `sinfo` to view the state of the cluster
  * `squeue` to see what jobs are holding things up
  * Checking files in `/var/log/slurm` on infosphere and the affected nodes
* Someone wants me to make an account for them!
  * Run this in `/root` on infosphere:

    ```bash
    cat your_user_list.txt | ./make_new_users.sh
    ```
* How do I run the [ansible](/technologies/tools/ansible) play?
  * From infosphere (this is important):

    ```bash
    cd ansible
    ansible-playbook -i hosts -f 50 --ask-vault-pass cluster.yml --skip-tags=install
    ```
  * The above command basically runs the default, updating-only play on all the cluster nodes, including infosphere.
* I want to upgrade a specific part of the cluster, how do?
  * There are a couple partitions in ansible:
    * `hpc`: All the [HPC](/machines/hpc-cluster) nodes
    * `hpcgpu`: Just [Zoidberg](/machines/hpc-cluster/zoidberg)
    * `ibm`: All the [Borg](/machines/borg-cluster) nodes
    * `ibmgpu`: All the Borg nodes with GPUs in them
    * `clustermaster`: infosphere itself
  * Run the corresponding ansible `.yml` playbooks from infosphere
* I would like to install a new version of something on the cluster, how do?
  * The current software names and versions are under `[fullcluster:vars]` in the hosts file in the [ansible](/technologies/tools/ansible) repository.
  * Change the version number to the latest available, and run the following command replacing `<software_name>` with something like `abinit` or `openmpi`.

    ```bash
    ansible-playbook -i hosts -f 50 cluster.yml --tags=install_<software_name>
    ```
  * The plays should automatically uninstall the old version for you when updating.
  * ***IMPORTANT NOTE***: If you update `pmix`, you also need to reinstall `slurm` and `openmpi`.
* After a slurm upgrade, everything went down. How fix?
  * Check that the slurm version is the same everywhere
  * `ansible fullcluster -i hosts -m command -a "bash -c 'systemctl disable slurmd; systemctl enable slurmd; systemctl restart slurmd'"` (disable slurmd on infosphere afterwards)
  * Really, just check the logs yourself, listen to error messages, Google your way to victory.
* How to recreate the `slurmdbd` database (last resort)?
  * `systemctl stop slurmdbd slurmctld && systemctl restart mariadb && mysql`
    1. `CREATE DATABASE slurm;`
       * If this command fails, skip to the end of this list
    2. `USE slurm;`
    3. `SHOW TABLES;`
    4. For every table in the database, `DROP TABLE <table_name>;`
    5. `exit`
  * `systemctl start slurmdbd slurmctld`
  * `sacctmgr add cluster hpc`
  * `find /cluster -type d | /root/make_new_users.sh`


# Setup

To set up a new Cluster node, you should follow these steps:

## Network it

Do the standard steps to add new entries for a node (or block of nodes) to DHCP and DNS.

{% content-ref url="/pages/-LKyHNaVNeKK4jQQx1Mw" %}
[DNS](/technologies/networking/dns)
{% endcontent-ref %}

{% content-ref url="/pages/-LMyKcsuAHkSR0WSwn3h" %}
[DHCP](/technologies/networking/dhcp)
{% endcontent-ref %}

Also make sure the switches/routers/cables are set up right.

## Install Ubuntu

The preferred method is to use Netboot, but a regular Ubuntu install stick works as well. If installing from an USB stick make sure your hostname matches the one specified in DNS/DHCP.

## Setup SSH

See [SSH Setup](#setup-ssh) page to learn more on how to setup SSH for the clusters.

## Run the Ansible play

First, make sure you add the node to an existing/new host group that has the `cluster` role. Then, you can just run `ansible-playbook`, sit back, kick your feet up, and wait for the install to finish.


# SSH Setup

Goes over setting up SSH in a cluster node

In order to remotely access a cluster from a local machine, or collect info from the node, you need to setup up SSH. This setup is crucial, but easy once you get used to it.

## Pre-installation

1. Make sure that the monitor and keyboard is **plugged into** the correct cluster.
2. If it is on, turn off the cluster, and then turn it back on in order for us to do the next step.
3. Spam F1 when the 'IBM Booter' comes up, it should open the Task Manager system.
4. Go to `Boot Options` and press enter on `ubuntu`. This should boot up Ubuntu. (This step assumes that you have installed Ubuntu 20.04 LTS, if not, you need to install Ubuntu using a USB Drive)
5. If booted up properly, it should send you the login page. Ask a clusters lead on what the username and password is for the node.

## SSH Installation

1. Make sure that there is internet by pinging into `8.8.8.8`. if not, inform a cluster lead.
2. Run `sudo apt install ssh` to install SSH into the cluster.
3. Run `sudo vim /etc/ssh/sshd_config` to edit this file using Vim.
4. Change this line from #PermitRootLogin:

```
#PermitRootLogin restrictpassword
```

to...

```
PermitRootLogin yes
```

5. Save the file (`:w` or `:wq`)
6. Run `sudo service ssh restart` to restart the ssh server within the cluster.
7. Once after you ran the previous command without any errors, run `sudo service sshd restart`. Don't worry about the throw errors, that's normal.
8. Verify that you can ping into the borg cluster by typing the command `ping borgXX.csl.tjhsst.edu`, where the XX is replaced by the number for the borg (i.e borg37)

If all passes, congrats! You just successfully configured SSH on a borg cluster! Next is usually to run `ansible` to make sure that the borg gets it correct dependencies.


# Administration

Everything on the cluster is managed through [Ansible](/technologies/tools/ansible) plays. This guide will show you how to use those plays, and how to add new ones.

## Organization

There's an existing organization to the play structure that helps keep everything simpler. It might not be the best organization, so it can be changed, but probably shouldn't be unless you want to re-write everything.

### Hosts and Roles

There are different host groups for each section of the cluster. `clustermaster` applies to infosphere, `hpc` applies to the HPC cluster, and `ibm` applies to the borg cluster. There are also `hpcgpu` and `ibmgpu` host groups that apply to the one gpu-enabled node in their respective clusters, and are not part of the regular cluster groups.

All machines part of the cluster, including infosphere, have the special `cluster` role applied to them in addition to the standard `common` and `auth` roles. `clustmaster` and `clustergpu` roles are responsible for installing more specific software, but the `cluster` role does all the heavy lifting.

There is also a `cluster.yml` play that applies all the basic roles to everything, but you should still manage parts of the cluster separately.

### `cluster` role

This role:

* Installs the base packages that are useful on the cluster
* Mounts cluster-specific NFS directory
* Copies correct cluster krb5.conf

What it doesn't do anymore:

* Installs and builds custom cluster software

All the software installation routines have been broken up into their own roles, all prefixed like `cluster-*`.

#### Custom cluster software

This is needed because the latest versions (with necessary functionality) may not be available in the repos.

* slurm
* openmpi&#x20;
* opencv
* abinit

#### Custom Software install process

The best way to make a new play to install a new custom software is by copying one of the existing plays (I like to copy openmpi). The general process goes like this:

* Install dependencies
* Download tarball
  * If it's been downloaded already, skip the rest of steps.
* Configure software
* Compile and install
* Set up environment

More details can be found by reading the plays themselves at [gitlab repo](https://gitlab.tjhsst.edu/sysadmins/ansible).

Please note, when adding new software to be installed, you make a new role for it and add the corresponding tags

### Flags to control custom software install

Sometimes, you just want to force reinstallation of the custom software, but are too lazy to edit the ansible play and change it back to normal afterwards. Don't worry; past sysadmins had that problem too! There a special command-line flag to force installation of a single package! Looks like this:

```bash
ansible-playbook -i hosts --tags=install_{package} [hostgroup].yml
```

Make sure you run the regular ansible play before installing software; you don't want to compile against out-of-date packages.

### Regular Ansible playbook run

After becoming root on infoprism:

```bash
cd ~/ansible
ansible-playbook -i hosts --ask-vault-pass hpc.yml --skip-tags=install
ansible-playbook -i hosts --ask-vault-pass ibm.yml --skip-tags=install
ansible-playbook -i hosts --ask-vault-pass clustermaster.yml --skip-tags=install
```

## Current concerns

These are problems with the cluster present at the time of documentation (March 2019). If you can fix them, good job!

* The cluster plays fail on new machines, needing to be run multiple times before going all the way through. Try to be better.
* Sometimes the mounts come offline, and an extra ansible command needs to be run on reboot (`ansible {hostgroup} [-k] -m command -a "mount -a"`).
* Some borg nodes can't netboot. Minimal issue, as a regular install stick works fine.
* Some borg nodes now aren't getting DHCP either.
* Graphics card compatability on Borg nodes is super spotty. Moving around cards until they work in a node.
* Dylan said to look at DHCP forwarding on [Imply](/machines/switches/imply) to attempt to fix HPC issue.
* `zoidberg` is currently being routed through the [Workstation](/services/workstations) VLAN in order to get networking due to the below problem.
* The HPC rack can't get DHCP addresses, ~~and most attempts at static IPs fail as well.~~ but it looks like setting a static ip through `/etc/sysconfig/network/ifcfg-bond0` works. The nodes currently up are fine as long as they don't get rebooted.
* `hpc7` and `hpc11` are super offline (have been for a while now), `hpc9`is offline due to the above issue (was rebooted).
* X11 forwarding doesn't work, problem with slurm. See [this bug report](https://bugs.schedmd.com/show_bug.cgi?id=5692).


# Slurm

If you aren't familiar with the layout of the HPC Cluster, it's highly recommended that you read the parent page, [Cluster,](/services/cluster) before delving into Slurm and running jobs, to avoid any confusion over terminology used here. After you have done so, please thoroughly read this page before using the cluster.

## What is Slurm?

Slurm is a free, open-source job scheduler which provides tools and functionality for executing and monitoring parallel computing jobs. It ensures that any jobs which are run have exclusive usage of the requested amount of resources, and manages a queue if there are not enough resources available at the moment to run a job. Your processes won't be bothered by anybody else's processes; you'll have complete ownership of the resources that you request.

## How do you use it?

Slurm is very user-friendly. However, it requires that you have an account on the HPC cluster, luckily students have an account on the first login. You don't necessarily have to have an academic use for the cluster, but keep in mind that any use of the HPC cluster is bound by the FCPS Acceptable Use Policy, just like the rest of TJ's computing resources, and academic jobs will have priority use of Cluster resources. Once you have had an account created for you, you can begin. Note that to utilize the cluster, you can use OnDemand.

### The Login Node - Outdated, use OnDemand instead.

If you want to compile and/or run a program, either that you have created or one created by somebody else, you will connect to the **login node**. The login node is a virtual machine with not very many resources relative to the rest of the HPC cluster, so you *don't* want to run programs directly on the login node. Instead, you want to tell Slurm to launch a **job**.

Jobs are how you can tell Slurm what processes you want run, and how many resources those processes should have. Slurm then goes out and launches your program on one or more of the actual HPC cluster nodes. This way, time consuming tasks can run in the background without requiring that you always be connected, and jobs can be queued to run at a later time.

The login node's name is **infosphere**. To connect to it, use SSH from remote.tjhsst.edu or a CSL workstation (`ssh infosphere` while on remote.tjhsst.edu or a workstation). If you don't want to remember "infosphere", "hpc" is aliased to infosphere and works just the same (`ssh hpc`). Connecting should be simple - you shouldn't have to enter a password as it should use your session from the computer you already logged in to. If not, just reenter your password that you use to log in to TJ resources (such as Ion).

Something important to note is that your home directory on the HPC Cluster is separate from your home directory on remote.tjhsst.edu and CSL workstations; this is because it's a different system optimized for speed. But don't worry, your Cluster home directory is shared across all HPC Cluster resources, so a program running on a compute node can access files that you create on the login node.

### OnDemand

OnDemand is serving as the replacement for the login node. Although infoprism (the replacement for infosphere) is still available, we strongly recommend that you run jobs using OnDemand. It's available in the apps menu on ion or at <https://ondemand.tjhsst.edu/>.

### Viewing information about the Cluster

To see information about the nodes of the cluster, you can run `sinfo`. You should get a table similar to this one:

```
PARTITION AVAIL  TIMELIMIT  NODES  STATE NODELIST
compute*     up   infinite      1    mix hpc9
compute*     up   infinite      8  alloc hpc[1-8]
compute*     up   infinite      3   idle hpc[10-12]
gpu          up   infinite      1  down* hpcgpu
```

* `idle` means that that block of nodes is not currently in use, and will be immediately allocated to any job that requests resources.
* `alloc` means that the node is busy and will not be available for any other jobs until the job is complete
* `mix` means that some of the cores within the node are allocated and others are free. Because this is annoying, it is good etiquette to allocate your jobs in multiples of full nodes (24 cores)
* `down` means that the node cannot currently be used.

To see which jobs are running and who started them, run `squeue`. You should see a table like this:

```
JOBID  PARTITION   NAME     USER    ST      TIME   NODES  NODELIST(REASON)
 882    compute   mpirun  2017ggol   R     44:56    12     hpc[1-12]
 884    compute    echo   2017ggol  PD      0:00     6     (Resources)
```

`ST` stands for state. The two common states are `R`, which means the job is currently running, and `PD`, which stands for pending. If the job is running, the rightmost column displays which nodes the job is running on. If the job is pending, the rightmost column displays why the job is not yet running. In this example, job 884 is waiting for six nodes worth of resources because job 882 is running on all 12 of the available nodes.&#x20;

If you're on OnDemand, it has a nice GUI menu for viewing jobs.

### Creating Programs to Run on the HPC Cluster

The HPC Cluster is comprised of 64-bit CentOS Linux or Ubuntu Server systems. While you can run any old Linux program on the Cluster, to take advantage of the parallel processing capability that the Cluster has, it's *highly* recommended to make use of a parallel programming interface. If you're taking or have taken Parallel Computing, you will know how to write and compile a program which uses MPI. If you aren't, <http://condor.cc.ku.edu/~grobe/docs/intro-MPI-C.shtml> is a good introduction to MPI in C. See below for instructions on running an MPI program on the cluster.

When compiling your program, it's best to compile directly on a cluster node (borg via ssh) or on infoprism (replacement for infosphere), so that your code is compiled in a similar environment to where it will be run. The login node should have all the necessary tools to do so, such as gcc, g++, and mpicc/mpixx.

**Important note: You won't be able to run mpicc or other special compilation tools until you load the appropriate programs into your environment. For MPI, the command to do so is** `module load mpi`**.** The reason for this is different compiler systems can conflict with each other, and the module system gives you the flexibility to use whatever compiler you want by loading the appropriate modules.

### Running a Job

And now the good stuff: running a job! Slurm provides 3 main methods of doing so:

#### `salloc`

Salloc allocates resources for a generic job and, by default, creates a shell with access to those resources. You can specify what resources you want to allocate with command line options (run `man salloc` to see them all), but the only one you need for most uses is `-n [number]` which specifies how many cores you want to allocate. You can also specify a command simply by placing it after all command line options (ex: `salloc -n 4 echo "hello world"`). This is currently the suggested way to run MPI jobs on the cluster. To run MPI jobs, first you must load the mpi module, as stated above (`module load mpi`). After that, simply run `salloc -n [number of cores] mpiexec [your program]`. Unfortunately, the displayed name of this job is, by default, just "mpiexec", which is not helpful for anyone. To give it a name, pass salloc (NOT mpirun) `--job-name=[name]`

#### `srun`

This is the simplest method, and is probably what you want to start out with. All you have to do is run `srun -n (processes) (path_to_program)`, where `(processes)` is the number of instances of your program that you want to run, and `(path_to_program)` is, you guessed it, the path to the program you want to run. If your program is an MPI program, you should not use `srun`, and instead use the `salloc` method described above.

If your command is successful, you should see `srun: jobid (x) submitted`. You can check on the status of your job by running `sacct`. You will receive any output of your program to the console. For more resource options, run `man srun` or use the official Slurm documentation.

#### `sbatch`

`sbatch` allows you to create batch files which specify a job and the resources required for the job and submit that directly to Slurm, instead of passing all the options to `srun`. Here's an example script, and assume you save it as `test.sh`:

```bash
#!/bin/bash
#SBATCH -n 4
#SBATCH --time=00:30:00
#SBATCH --ntasks-per-node=2

srun (path_to_program)
```

You could then submit the program to slurm using `sbatch test.sh`. This would tell Slurm to launch the program at `(path_to_program)`, and to launch 4 tasks, limit the maximum execution time to 30 minutes, and require that no more than two tasks run on a specific system. Here are some other examples: <https://www.hpc2n.umu.se/batchsystem/examples_scripts>.

### X forwarding

Sorry, it doesn't work yet.

If it did, and your program outputs graphics, then you need to X-forward (X is linux graphics) from the remote machine (infosphere) to your machine. To do this, use the `-X` flag when `ssh`-ing all the way to infosphere. Then, you need to use the `--x11` flag when running a slurm command. An example series of commands is listed below:

```
[you@yourmachine:~]$ ssh -X 20xxyyou@remote.tjhsst.edu
[20xxyyou@ras2:~]$ ssh -X infosphere
[20xxyyou@infosphere:~]$ srun --x11 --other_flags ./your_program
```


# Slurm Administration

This page is intended to serve as a guide for Sysadmins who need to administrate the Slurm system running on the HPC cluster. If you're a regular user, this information probably won't be very interesting to you.

Here is a Slurm quickstart from their developers: <https://slurm.schedmd.com/quickstart.html>

## Accounts vs Users

The Slurm accounting system separates the ideas of Accounts and Users, which is slightly confusing at first. When you look at it from the higher-level functioning of Slurm though, these concepts make sense.

An **Account** is a method of controlling allowed resources and accounting for resources for a user or a group of users. For example, if you have a specific student group which you wanted to give elevated resource allowances to, you could create an Account for that group and attach their Users to that Account. Perhaps most importantly, names of Accounts are arbitrary, and don't have to match LDAP/Kerberos usernames.

In contrast, a **User** is purely meant to map Linux accounts (pulled from LDAP) to a Slurm account. **The usernames of Slurm Users MUST MATCH the person's username in LDAP**.

## Account/User Creation

All of the cluster nodes use standard CSL NSS-LDAP for authentication and authorization to cluster machines (the login node, compute nodes, and GPU node), but Slurm must have a User registered in its accounting system for that user to be able to run jobs using Slurm. Since Slurm authenticates users based on their Linux username, no extra passwords or LDAP configuration is necessary; once a user has their account added to the Slurm database, they should be able to seamlessly connect to the login node (infosphere) using their normal credentials and be able to run Slurm jobs without extra authentication.

`sacctmgr` is the tool used to manage Slurm users and accounts. To manage accounts, you must be root on infosphere or any other node of the cluster.

### Creating an Account

Right now, since different users may have different resource requirements, the current policy is to create a different Account for each User who wants to use the cluster. To do so, run the following:

```
sacctmgr add Account (username)
```

### Creating a User

After you've created a user's account, you can then add a User attached to that account:

```
sacctmgr add User Accounts=(username) (username)
```

### Creating a Cluster Home Directory - Deprecated, Use /csl/users

For speed, the cluster uses a separate user storage system than most other public-facing systems (which use AFS). On all cluster systems, user home directories are located under `/cluster`. Users' home directories are currently not automatically created due to issues with the pam\_mkhomedir.so module and SELinux, so you have to manually create the user a home directory:

```
cp -r /etc/skel /cluster/(username)
chown -R (username) /cluster/(username)
```

## Partitions/Nodes

Slurm has a system of partitions that help segment work.

In our setup, we have two partitions \`compute\` and `gpu`.


# Borg

Pertinent things to know:

* We have 40 (`borg[01-40]`)
* They are named after constellations or, in rare cases, `borgw[01-40]`
* They all run the same OS ([Ubuntu Server](/technologies/operating-systems/ubuntu-server)) and use the same [Ansible](/technologies/tools/ansible) play as the rest of the cluster.


# Printing

The CSL's printing infrastructure

## Printing

Printing is a production service offered by the Computer Systems Lab. We provide the means for students to print from Ion and the CSL workstations.

The contact person for the printing service and associated infrastructure is [the Printing Lead](/general/sysadmins-list#current-leads).

### Printers

We currently have three functioning printers:

* printer202 (in Room 202)
  * This is a HP LaserJet P3015
* 198.38.18.3 (in Room 200C)
  * This is a HP LaserJet P3015
* 198.38.18.4 (in Room 200)
  * This is a HP LaserJet P3015

### Ion Printing

There is a web interface to provide printing services on Ion at <https://ion.tjhsst.edu/printing>. Ion uses the CUPS server at `cups2.csl.tjhsst.edu` to manage jobs. Relevant code can be found [here](https://github.com/tjcsl/ion/tree/master/intranet/apps/printing).

## Workstation Printing

Each workstations uses the CUPS server at `cups2.csl.tjhsst.edu` to manage jobs and send them to the printers.

## Abuse Protection

Jobs are limited to 10 pages. Abuse of printing privileges may result in appropriate punishment as determined by the Faculty Sponsor and lead Sysadmins.


# Setup

CUPS is a standards-based open-source printing system for Unix-like operating systems. You can read more about CUPS at its [Wikipdia page](https://en.wikipedia.org/wiki/CUPS). The Arch Wiki also has a [good article about it](https://wiki.archlinux.org/index.php/CUPS.).

## Installation

To setup a CUPS server, it is necessary to create a VM server. Follow the instructions found in the QEMU pages of these docs to create a VM server. It should be on the 1600 VLAN with DHCP and DNS configured.

You should run the Ansible play `cups.yml` to create the base VM config, install the CUPS server, and install appropriate drivers.

## Configuration on VM

After accessing the VM over SSH, you should add any users you wish to allow to administer the CUPS server to the `lpadmin` group with `usermod -aG lpadmin <USERNAME>` (as root).

You should edit the CUPS conf(`/etc/cups/cupsd.conf`) to allow access to the CUPS remote administration website for Sysadmin VPN IPs. This can be done by adding `Allow from <IP ADDRESS>` directives underneath `<Location />` and `<Location /admin>`.

You should also add `Listen <ADDRESS>` directives near the top of `cupsd.conf` to specify where the CUPS server should listen. In general, the CUPS server should listen on port 631.

{% hint style="info" %}
You must always restart the CUPS server after editing `cupsd.conf`. You can restart the server with `systemctl restart cups`.
{% endhint %}

## Web Configuration

To access the web interface, you should head over to the address of your CUPS server (with `:631` specified at the end). Once you reach the web interface, you should see a screen similar to the one below.

Click on the `Administration` tab at the top to view the main administrative interface. Most administrative actions can be performed here. On the screen, you can see various buttons and their functions are self-explanatory.

## Add Printer

To add a printer through the web interface, you should click on the `Add Printer` button.

You will most likely get prompted for your credentials. Enter either your root credentials or the credentials of any user in the `lpadmin` group. You will then proceed through a series of prompts that will ask for information about the printer.

* Under network printers, most likely you will select `App Socket/HP Jet Direct`. You should obtain this information from the printer manual.
* An example URI is `socket://printer202.csl.tjhsst.edu:9100`.  You should obtain this information from the manual.
  * Note: The printers should be on the workstation VLAN and connected to a port configured for that VLAN.
* For name, fill in a descriptive name for the printer.
* For description, fill in a description of the printer.
* For location, fill in the location of the printer.
* You should generally allow connection sharing.
* For Manufacturer and Model, select the appropriate ones for your printer.

Once your printer has been added, select the drop down menu and click `Print Test Page` to test if your connection is working. Repeat these steps for any other printers.


# Troubleshooting

**Help! I don't know what I am doing.**

Ask someone more experienced for help.

**I can't access the admin page**&#x20;

If you don't see a CUPS error, that means the CUPS server is not running. Start the server. If you see a CUPS error, look at the logs in `/var/cups` for information.


# WWW

The CSL's web server

**WWW** is the TJ CSL's main public-facing webserver. In addition to just serving the sites hosted on it, it is also responsible for hosting various website at `*.tjhsst.edu`, while others are hosted on [Director](/services/director).

The contact for WWW and related infrastructure is [the WWW Lead](/general/sysadmins-list#current-leads).


# Administration

This page describes how to accomplish certain administration tasks on [WWW](/services/www)

## SSL

We use Let's Encrypt for SSL, using Certbot. Let's Encrypt certificates expire every 90 days and are renewed every 60 days. Renewal is automated, but several other servers use the wildcard certificate and must pull the updated one. The most important of these are the mail servers, which use the certificate for SMTP. The script `update-ssl.sh` in the root home directory of Casey and Smith should handle this. After certificates are renewed, run the update-ssl script on:

* Mail servers (Smith and Casey)
* IPA servers, for the web ui
* Monitor/Grafana

## Scripts

This section contains various other scripts to do useful things on [WWW](/services/www).

### What to do if the webserver goes down

1. Log in to remote.tjhsst.edu (or if you're already on the internal network, that's fine too)
2. `ssh root@www`
3. `systemctl restart nginx`

   This restarts nginx and ensures that the service manager is still in a consistent state. The website should work after this (if not, try clearing cache/etc, it's possible a redirect to an error page might've been cached, although it shouldn't be).

### If SSL doesn't renew automatically

The certbot command is `certbot certonly`\
`--manual \`\
`--preferred-challenges dns \`\
`--manual-auth-hook /usr/local/bin/certbot-ipa-dns-update.sh \`\
`--deploy-hook "nginx -s reload" \`\
`--manual-cleanup-hook /usr/local/bin/certbot-ipa-dns-cleanup.sh \`\
`-d tjhsst.edu \`\
`-d '*.tjhsst.edu' \`\
`--non-interactive --agree-tos -m lead-sysadmins@tjhsst.edu --no-eff-email \`\
`--expand`

You can try running this manually to see the error. You can also look at the script in `/usr/local/bin/certbot-ipa-dns-update.sh`  to see what it's supposed to do.&#x20;


# Sites


# Web Proxy

The CSL does not run TJ's web proxy service. However, we do serve the proxy automatic configuration script at [pac.tjhsst.edu](https://pac.tjhsst.edu) and the proxy setup instructions at [proxysetup.tjhsst.edu](https://proxysetup.tjhsst.edu) and on [LiveDoc](https://livedoc.tjhsst.edu).

#### Proxy Setup Script:

{% file src="/files/-LOGduuxlKupavmzFGE3" %}
proxysetup.pac
{% endfile %}


# Setup


# Troubleshooting


# Academic Services

The CSL's public-facing services supporting academic endeavours


# Tin


# Othello


# Administration


# Setup


# Technologies


# Web


# Nginx


# Django

**Django** is a Python web framework designed for enterprise-scale application. [Ion](/services/ion), [Director](/services/director), and [Othello](/services/academic-services/othello) are all Django applications.

For more information about the framework itself, see the Django website at <https://www.djangoproject.com/>.

### Quickstart Guide

This guide is meant to be a simple explanation of how Django works, not really a complete one. You should really read the entire thing twice through because there's so much interconnected stuff. Really the thing to read is <https://docs.djangoproject.com/en/2.1/intro/tutorial01/> but this is more of a reference guide so meh.

#### Making/Getting a project

If there is already a git repository containing a Django project, you just have to `git clone` it and go to the directory it lives in to start working.

Otherwise, if you are starting a new project, you must install Django globally first, then run the command:

```bash
django-admin startproject <project-name>
```

This will create a new directory `project-name/` which you can `git init` a repository in and start working on.

#### Installing Django

**In a virtual environment**

I like to use virtual environments to run Django code, keeping their packages separate from cluttering up my main Python environment.

First, to create a virtual environment, run the command:

```bash
pip install --upgrade virtualenv
python -m virtualenv <venv-folder>
```

in the directory you want to create a `venv-folder/` in.

Then, you must `source activate venv-folder/bin/activate` (or, if you are on Windows, `venv-folder\Scripts\activate.bat`) in order to activate the virtual environment.

**Which packages tho**

You are now ready to actually start installing Django packages in your virtual environment.

If you have cloned a repository from somewhere else, there will usually be a file called `requirements.txt` at the root. Run

```bash
pip install --upgrade -r requirements.txt
```

to install all the packages it specifies. This is better than reading the file yourself because pip will automatically take care of version control and whatnot.

A sample `requirements.txt` is listed below:

```
daphne
django
requests
Twisted[tls,http2]
```

#### Django's Directory Layout

So apparently the creators of Django decided they didn't like how normal people organized they files, and also didn't think they should add any custom organization options, so here we are with a pretty strict way of doing Django projects.

Fortunately, it's also a pretty good way and teaches best practices for modularity so there's that.

For the rest of this section, we will assume your project is called `your_project` containing a single app called `the_app`.

**Main files**

Let's say you are in the root directory of your new Django project/git repository. You should see these files/folders:

* `manage.py`: the main helper script for developing with Django. Can start the server, run db operations, etc
* `your-project/`: Your main project folder, where all of your code goes. This will have a few sub-files, as denoted by sub-bullets (sub-folders are discussed in a later section)
  * `settings.py`: Where all of Django's settings are stored. This file is massive, an absolute unit. Specifics discussed later.
  * `urls.py`: Where Django looks for all the URLs it should handle. URLs can be manually specified, included from other files, and all correspond to Views defined in Apps (next section)
  * `wsgi.py`: A small file containing everything needed for a Django server to actually server your app. Doesn't really need to be edited

There can be more files in here, but they will be project-specific.

**Apps**

Now, let's move on to what actually makes Django cool: **Apps**! Apps are small, supposedly independent modules that take care of one task. Every app is a subfolder (`the_app/`) in the main project directory () In the Othello Server, for example, there is one app each dedicated to:

* Authentication (`auth`)
* User sessions (`users`)
* Running games (`games`, the biggest one)

Because apps are what makes up the meat of a Django project, they contain the most sub-files. The automatically created ones are listed below, but apps can contain as many sub-files as they want to get the functionality they need.

**views.py**

This is where you write the code to handle what happens when someone visits a page. Views (really just Python functions that return HTML with Django helpers) defined in this file are referenced from the main `urls.py` file or, for more complicated apps, an app-specific `the-app/urls.py` file which in turn is included in bulk in the main `urls.py` file. Got it?

**models.py**

This file defines what database objects Django needs to create. Django is super cool in that you can basically write regular ol' Python data storage objects and Django will convert them to work with any database backend you use. If you make changes to this file, you must also update the database with `python manage.py makemigrations && python manage.py migrate`

**apps.py**

Some lame file you needs to have in order for Django to not complain. Example:

```python
# your_project/the_app/apps.py
from django.apps import AppConfig


class TheAppConfig(AppConfig):
    name = 'your_project.apps.the_app'
```

**admin.py and tests.py**

Unless you do stuff on Ion or Director these don't really matter. `admin.py` defines models accessible from django-admin, and `tests.py` defines testcases so you have a less chance of breaking your code by accident (super lame).

**Templates**

The folder `your_project/templates/` contains all the [Jinja2](http://jinja.pocoo.org/) templates for you Django project. Basically stores all the HTML/JS/CSS that should be dynamically rendered (mostly HTML).

If you want good text highlighting, you might want to name these ending in `.j2` instead of `.html`. We don't really do that yet though.

**Static files**

The folder `your_project/static/` contains all of the static files, like most of your JS/CSS and all of your images. Note that this folder only really has to be here for debugging purposes: in production, Django won't touch it.

#### `settings.py` layout

Some important variables:

* `DEBUG`: controls whether we are in debug mode or not, will enable static file hosting and automatic server reload when set to `True`
* `ALLOWED_HOSTS`: All the hostnames Django will allow itself to be accessed from. `"localhost"` or `"127.0.0.1"`should be in there if you are developing.
* `INSTALLED_APPS`: All the Apps that Django will load. If you want to add an App you made to the list, append `"your_project.apps.the_app"` to it.
* `MIDDLEWARE`: some hoodoo-vooodoo black-magic security wizardry, best not to touch it unless a library says you should add them to it.
* `ROOT_URLCONF`: The file Django loads urls from. Should be set to `your_project.urls` by default and stay that way.
* `TEMPLATES`: I don't even know, man. Best not to touch it.
* `LOGGING`: All the places for Django to log it's runtime messages. You should read the actual documentation for this.
* `WSGI_APPLICATION`: The file a Django server should hook into in order to start the server. Why it is called WSGI will be covered later.
* `DATABASES`: All the places Django should store data

There are a ton more variables, but most are simple enough to understand/are part of an external library that builds on Django. Most of the time, you will only be touching a very limited subset of variables when developing.

#### Adding a simple page

As an example to demonstrate the knowledge mountain that has been piled upon thee by the above sections, let's walk through adding a simple templated page to an existing project `your_project`

1. Add the file at `your_project/templates/sample-page.html`

   ```markup
    <html>
      <head>
        <title>A page!</title>
      </head>
      <body>
        <h1>
          Your random number is: {{ the_number }}
        </h1>
      </body>
    </html>
   ```
2. Add the app using `manage.py`

   ```bash
    python manage.py startapp the_app
   ```
3. Add the view to the app

   &#x20;\`\`\`python

   **your\_project/apps/the\_app/views.py**

   &#x20;from django.shortcuts import render

   &#x20;from random import randint

````
def sample_view(request):
  n = str(randint(1, 100))
  return render(request, "sample-page.html", {'the_number': n})
```
````

1. Add the view to `urls.py`

   ```python
    # your_project/urls.py
    """big django comment"""
    from django.conf.urls import url, include
    from django.contrib import admin

    from .apps.the_app import views as the_app_views

    urlpatterns = [
      url(r'^randnum$', the_app_views.sample_view, name="sample"),
    ]
   ```
2. Add the app to `settings.py`

   ```python
    # your_project/settings.py

    """
    ...
    A bunch of stuff
    ...
    """

    INSTALLED_APPS = [
      # All the existing apps
      "your_project",
      "your_project.apps.the_app",
    ]

    """
    ...
    A bunch more stuff
    ...
    """
   ```
3. You're done! Start the server using `python manage.py runserver 8001` and go to `http://localhost:8001/randnum` to (hopefully) see your random number!

#### Django Channels

This is required for Django to support. I highly recommend reading <https://channels.readthedocs.io/en/latest/> because I can't explain it too well yet. TL;DR you need to do a hecka bunch more stuff.

#### Running the server

**In development**

First, make sure `DEBUG=True` is set in your `settings.py`, then you can run

```bash
python manage.py runserver {optional_port}
```

at the root of your Django project. If that fails for some reason, or some website functionality is limited, you might have forgotten to create the database. Run

```bash
python manage.py makemigrations && python manage.py migrate
```

to maybe fix that.

**In production**

In production, we need to have a few more things set up.

**Static files**

Django doesn't like to serve static files (because it is Python and slow), so it wants something else like [Nginx](/technologies/web/nginx) to take care of that for it. How the whole proxying setup works is explained in the [Nginx](/technologies/web/nginx) page.

**A better webserver**

There are a ton better, much more performant [WSGI](https://wsgi.readthedocs.io/en/latest/what.html)/[ASGI](https://github.com/django/asgiref/blob/master/specs/asgi.rst)-compatible webservers than the one Django comes with. Good WSGI-only ones include [Gunicorn](https://gunicorn.org/) and [uWSGI](https://uwsgi-docs.readthedocs.io/en/latest/), while ASGI (websocket-compatible) ones include [Daphne](https://github.com/django/daphne) and [Uvicorn](https://www.uvicorn.org/). Choose one and set it up in your virtual environment.

**A nice startup script**

Using `daphne` as an example production server, here's what a complete startup script would look like:

```bash
#!/bin/bash

cd $DJANGO_ROOT
source $VENV/bin/activate
daphne -b 0.0.0.0 -p 8001 django_project.asgi:application
```

Assuming you have everything set up right (including static file proxying), running this script should make the server accessible through the proxied port.

Now you can add `ExecStart=/usr/bin/bash your-script.sh` to a systemd unit to make it the server at boot if that's what you want.

### Trivia

* Django is very good and much better than Flask for large web projects
* You can remember how to pronounce "Django" by remembering that "**Jango** Fett died in Star Wars Episode II: Attack of the Clones"
  * You should never say "duh-Jango" because that makes you sound weird
* Django is pretty resource intensive and spawns a heck ton of threads, which can especially bog down older laptops so be careful.


# PHP-FPM


# Node.js


# Supervisord

**supervisord** is a system that allows its users to control a number of processes on UNIX-like operating systems.

[GitHub repo](https://github.com/Supervisor/supervisor)

## Managing Configuration

**supervisord** is managed via a configuration file at `/etc/supervisor/supervisord.conf`  (or applicable sub directories).

**supervisor** has a CLI interface which administrators can use to control programs managed by **supervisord.**

{% hint style="warning" %}
It is important to understand the distinction between `reread` and `update` . These commands have DIFFERENT FUNCTIONS. `reread` scans a configuration file for changes, but an `update` IS needed afterwards.
{% endhint %}


# DBs


# PostgreSQL

PostgreSQL is our most used relational database system in the Lab.

The [Wikipedia article for Postgres](https://en.wikipedia.org/wiki/PostgreSQL) gives a fairly thorough overview.

One of the higlights of the PostgreSQL community is their wealth of documentation at <https://www.postgresql.org/docs/manuals/>. Their manual is hence a good read, even though it is 2000+ pages long. Reading that manual will give you a better introduction to Postgres than our documentation could cover.

The PostgreSQL team uses <https://git.postgresql.org/gitweb/?p=postgresql.git> as their central Git repository.


# MySQL

[MySQL](https://dev.mysql.com) is an open source relational database that we use for a variety of applications in the Lab.

Their documentation is very useful: <https://dev.mysql.com/doc/>.


# Authentication


# Passcard

The CSL passcard contains the root passwords for all CSL systems. The passcard is maintained in a git repository hosted on GitLab. The repository is maintained by the lead Sysadmins and any questions, concerns or bug reports should be directed to them.

### Requirements

To use the passcard system, you must have the following:

* &#x20;Git
* &#x20;GPG
* &#x20;A GPG key
  * &#x20;If you are using the official CSL passcard, the public key should be signed by a lead Sysadmin or by someone with all the lead Sysadmins in their trustnet and also stored on a public keyserver.
* &#x20;Python3
  * &#x20;To use the wrapper script

### Accessing the Passcard

The git repository is accessible via GitLab at [gitlab.tjhsst.edu/sysadmins/passcard](https://gitlab.tjhsst.edu/sysadmins/passcard). To clone the repository, run the following command: `git clone git@gitlab.tjhsst.edu:sysadmins/keybase-passcard.git`. You can clone it from outside the TJ network, but to access the passcard repository you MUST have a GitLab account.

### Using the Passcard

The passcard git repository has a wrapper script (passcard.py) along with GPG encrypted passwords individually encrypted in the passwords folder. Since the passwords are individually encrypted, each password is encrypted with the keys of the people who should have access to it. For example, somebody can have access to [Core0](/machines/switches/core0)'s password without having access to [Waitaha](/machines/ceph/waitaha)'s password. You can use gpg yourself and decrypt these passwords, or you can use the wrapper script which does it all for you.

\
&#x20;For help with the wrapper script, run it without any arguments. Here are the commands you can use:

`./passcard.py get antipodes` will show you the decrypted password for antipodes and antipodes-ilo (to use most commands, you must have gpg installed with your private key imported).

`./passcard.py dump` will make a nice, two-column passcard to stdout of all the passwords you have access to.

`./passcard.py addkey antipodes "Chris Reffett"` will add Chris Reffett's public key to the antipodes passcard so he can then decrypt it.

`./passcard.py add` will give you an interface for adding a new passcard.

Changes to the passcard locally will be pushed automatically by the script to the GitLab repository.

There is also a file `sysadmin_keys.txt` in the repository that contains GPG keys for each of the Sysadmins, as well as the faculty sponsor. Import them at your own risk, but if you wish to import all of them, you can do that with `cat sysadmin_keys.txt | grep -v '#' | grep -Po "0x[0-9A-Za-z]+" | xargs gpg --recv-keys` on a Linux system.


# GPG Usage

**GPG** is the underlying technology used to control access to secret material on the CSL [Passcard](/technologies/authentication/passcard). For information on GPG read its [Wikipedia article](https://en.wikipedia.org/wiki/GNU_Privacy_Guard). The GnuPG community has excellent documentation on its [website](https://gnupg.org/documentation/howtos.html).

## High-level Overview

GPG works through a public-private key pair. Text and data can be encrypted with the public key component of the key pair (which can be shared publicly with little restriction). The encrypted data, however, can only be decrypted with the private key component of the key pair. GPG has other uses such as signing messages with private keys and authentication with a private key but those functionalities are not used by Passcard.

## Generating

GPG key pairs should be generated and stored on a computer you trust. Any individual with root access would be able to read the private part of your GPG key pair.

### Quick

The GnuPG community has more detailed documentation on this but, in essence, to generate your key pair, you need to run the command `gpg --gen-key`. You will be prompted to enter your name, email address, and private key passphrase.

### Manual

When generating the key, you may want to specify additional configuration options. Running `gpg --full-gen-key` It will prompt you for the type of key (generally RSA is good), a key size (anything 2048 bits or longer is strong enough), a validity time, your name, email address, a comment, and private key passphrase.

## Exporting

You can view all secret (private) keys you have stored on your computer with `gpg --list-secret-keys` and `gpg -K`. You can view all the public keys you have in your key ring with `gpg --list-keys` or `gpg -k`.

An example key can be found below:

```
pub   rsa4096/0x67198197EBDE4957 2018-01-03 [SC]
      34248131BE91E92FEE033DC567198197EBDE4957
uid                   [ultimate] Theo Ouzhinski (Education) <2020fouzhins@tjhsst.edu>
sub   rsa4096/0x46FB05EE18EBA895 2018-01-03 [E]
```

In this example, `0x67198197EBDE4957` is the key ID. By default, most installations of GnuPG will default to the short format which in this case is `EBDE4957`.

You can export your public key in ASCII format (to send in emails or to other people) with `gpg --export --armor <SUBSTRING OF NAME/EMAIL OR KEY ID>`.

## Keyservers

{% hint style="warning" %}
GPG keys are shared publicly through GPG public key servers. However, due to [https://www.google.com/search?hl=en\&q=sks%20attack](https://gist.github.com/rjhansen/67ab921ffb4084c865b3618d6955275f), we caution against synchronizing against the main Synchronizing Key Servers.  If you need to&#x20;
{% endhint %}

{% hint style="info" %}
Once a key is on a public key server, it cannot be removed. IDs, signatures, and expiration dates can be added to keys on the key servers but not removed.
{% endhint %}

You can send your key (or any other key in your keyring) to a key server by running `gpg --keyserver <KEYSERVER URL> --send-keys <KEY ID>`.

## Receiving

All public keys that are known to you are stored locally in your public key keyring. If you have a copy of someone's public key, you can import it with `gpg --import <FILE PATH>`.

{% hint style="info" %}
You should generally have all Sysadmin's public keys in your public keyring. This is useful for determining who is on a passcard (with `./passcard.py who <SERVER>`)
{% endhint %}

## Signing

{% hint style="info" %}
Do not sign someone's key unless you are sure that it is their key. Signing keys are at your discretion.
{% endhint %}

When you sign someone's public key, you are vouching for their identity and the key's validity. The initial purpose of signing public key's was to create a network of trust. The Sysadmins have their own network of trust. Each sysadmin should have a trust path to other sysadmins (this may not always be the case but is general good practice).

To sign someone's public key, run `gpg -u <SUBSTRING OF YOUR NAME/EMAIL OR YOUR KEY ID> --sign-key <SUBSTRING OF OTHER'S NAME/EMAIL>`. You will be prompted to confirm your signature. You can then export and commit it to the passcard repository.


# SSHD


# SSH Passwordless Login

**SSH Passwordless Login** is set up on all CSL machines in order to seamlessly SSH into different machines without having to type in your password every time. This is achieved using user SSH keys.

In order to set up passwordless login, run `ssh-keygen` and hit enter through the setup wizard. This will create two files, `id_rsa` and `id_rsa.pub`, in `[YOUR HOME DIRECTORY]/.ssh`. Log into a remote access server, create the `.ssh` folder in there (i.e., `mkdir ~/.ssh`), and upload the two files in there. Run `chmod 600 ~/.ssh/id_rsa`; this fixes permission issues. When you're at school, visit <https://ipa.tjhsst.edu> and login with your CSL username and password. Go to your profile page. Click on "Add" next to "SSH Public Keys" and upload the contents of `id_rsa.pub`. You should now be able to SSH without a password to any machine that you have authorization for.


# FreeIPA

The CSL's authentication system

**FreeIPA** (<https://www.freeipa.org>), which stands for "Free Identity, Policy, and Authentication", is an open-source identity management system that provides the CSL with centralized account (Name Service Switch, or NSS) and host management services. FreeIPA was implemented lab-wide on June 16, 2023, replacing the CSL's old LDAP/Kerberos setup dating back to 2007.

## History

Previously, the CSL used NIS to store network user information. However, when the decision was made to integrate CSL accounts and authentication with Windows Active Directory (previously all CSL accounts were managed separately and required an application form to receive), LDAP was chosen to replace NIS as the backend for the NSS database.

Integrated authentication using LDAP and [Kerberos](/obsolete/kerberos) was initially deployed in lab 231 during the spring of 2006. Sun Directory Server 5.2 was used at the time, replicated from sol across what are now known as chuku and ekhi. During the summer following, LDAP was moved into a VMWare virtual machine known as daystar in order to run LDAP on a faster system. However, for reasons not completely understood, the VM subsequently developed problems during the fall of 2006 and resulted in NSS becoming painfully slow on both rockhopper (at that time used for all of lab 231 and 16 LTSP nodes in the CSL) and the rest of the CSL workstations. In order to remedy the situation, `/etc/passwd` was rapidly deployed as a flatfile across all affected systems. Hesiod was subsequently set up as the NSS database for the remainder of the school year and the beginning of the next.

During the winter of 2007-08, NSS was switched back to LDAP following various discussions. LDAP was configured on chuku and mihr, running Sun Directory Server 6.

Upon reception of the [Sun Academic Excellence Grant](/machines/history/2008-sun-aeg), LDAP was moved into the LDOMs (UltraSPARC-specific virtual machines) ldap1 and ldap2 running on [Ohare](/machines/other/sun-servers/ohare) and Logan. The service was eventually migrated to KVM virtual machines openldap1 and openldap2.

By the early 2020s, this setup was starting to show its age; account creation was a cumbersome, several-stage process that was prone to failure, LDAP was hard to integrate with systems like Single Sign-On (SSO), and there was a lot of cruft left over from fifteen years of the old setup. The use of FreeIPA as a replacement for the legacy system had been considered since 2020, but it wasn't until 2023 that the decision was made to switch to FreeIPA, largely because the lab was being shut down anyway for Ceph upgrades. Migration work started on May 31, 2023 with the installation of a FreeIPA server on Utonium. The install was moved to Sauron on June 16, a couple hours after the school year ended. (It was going to be moved shortly after school started, but had to be paused last-minute after an Ion lead remembered that people needed to see their bus locations.)

## Systems

The CSL has three FreeIPA servers. Sauron serves as `ipa1`, the primary server. `ipa2` and `ipa3` are VMs. In addition to FreeIPA, these three machines serve as lab NTP servers, and `ipa1` is also the lab's DHCP server. However, these functions (FreeIPA, NTP, DHCP) function largely independently of one another; the colocation is mostly for historical reasons and to save on resources.

## Features

The nice thing about FreeIPA is that it takes care of a lot of stuff on its own. It comes with a web UI to make changes, as well as an API and some handy Python libraries. We have built-in support for host-based access control instead of relying on SSH configs or the old system that was implemented in OpenLDAP. It makes the account management process a lot easier.


# Storage


# NFS

The Network File System (or NFS), is, as the name suggests, a network file system. In this case, we export a CephFS directory over the network to store user data. NFS has been used for this purpose at various points in the CSL's history (it's mentioned in documentation since 1996!), though AFS has been the predominant choice for the use case over the last 20 years. However, AFS has become slow and hard to maintain, so the decision was made to switch to NFS in August 2023, especially since it integrates with FreeIPA and automatically only mounts directories that are in use (e.g. logged-in users' home directories instead of all 2000 of them, which is a big difference!) The NFS share is located at `/nfs` within CephFS and at `/csl` on all clients.


# Ceph

## Introduction

The Computer Systems Lab uses [Ceph](https://ceph.com) as its main storage infrastructure. We chose to use Ceph because of its scalability, redundancy, and reliability.&#x20;

Ceph is developed by Red Hat, Inc. and is used by organizations like CERN, Cisco, T-Mobile, and various educational institutions around the world.

## Servers

Currently, we have 3 OSD servers and 3 monitor/manager/metadata servers in the Ceph cluster. Each OSD server ([karel](/machines/ceph/karel), [wumpus](/machines/ceph/wumpus), and [stobar](/machines/ceph/stobar) ) has 12×4TB HDD and 2×400GB SSDs.

## Architecture

A Ceph promo video is available [here](https://www.youtube.com/watch?v=0bdIcqgAbKQ).

[This video](https://www.youtube.com/watch?v=PmLPbrf-x9g) provides a good technical overview of Ceph from the Ceph Project Lead.

Ceph is composed of four different daemons: monitors, managers, object storage daemons, and metadata server daemons.  The backend storage layer is called the Reliable Autonomous Distributed Object Store (RADOS).

&#x20;Ceph was developed from the ground up to protect against hardware failures and corruption by distributing data across multiple hard drives hosted on multiple servers. The data written to each hard drive is managed by an object storage daemon (OSD) and the state of the cluster is managed by a set of monitors (mon). Using a state-of-the art algorithm, data is stored in various placement groups (PGs) which are replicated across multiple OSDs and served out to appropriate clients by the monitors.

The data itself is distributed according to the Controlled, Replicated Under Scalable Hashing (CRUSH) algorithm.  At least a majority of the monitors must agree to the state of the cluster and resolves differences in the main cluster map.  The monitors also store the CRUSH map.

Manager daemons provide an interface for outside systems to access data about the cluster.

Metadata server daemons are responsible for managing metadata for the CephFS file system.


# Setup

{% hint style="warning" %}
For our G10 servers, do not use Ubuntu Server 16.04.  Instead, use Ubuntu Server 18.04.
{% endhint %}

{% hint style="info" %}
You can find setup instructions within the [Ceph documentation](https://docs.ceph.com)
{% endhint %}

The install steps with `ceph-deploy` are detailed in the [Ceph documentation](https://docs.ceph.com/docs/master/start/).


# Backups

## RBD Snapshots

To create an RBD snapshot, run&#x20;

```bash
rbd snap create <IMAGE NAME>@<SNAP NAME>
```

where `<SNAP NAME>` is the requested snapshot name.

For example, to snapshot `virtual-machines/steeltoe` with a snapshot named `20190108` :

```bash
rbd snap create virtual-machines/steeltoe@20190108
```

We use the `YYYYMMDD` format as our naming convention for snapshot based on the day of the snapshot.  For example, a snapshot made on January 1, 2019 would be `20190101` . Any further snapshots have a `-1` (etc.) appended.

## CephFS Snapshots

To create a snapshot of a CephFS directory, run:

```bash
mkdir <PATH TO DIR>/.snap/<SNAP NAME>
```

More information is available at <https://github.com/ceph/ceph/blob/master/doc/dev/cephfs-snapshots.rst#creating-a-snapshot>

We use the same snapshot naming convention as RBD snapshots.


# CephFS


# Operating Systems

The CSL currently runs two separate operating systems on its servers: Ubuntu and AlmaLinux. Workstations currently run Ubuntu, though Debian is being considered as a replacement.

The CSL used to run a multitude of other operating systems, mostly on Sun hardware. These included:

* (Sun) Solaris
* Gentoo
* FreeBSD/OpenBSD
* Whatever the [Cray SV1 ran](/obsolete/cray-sv1-supercomputer)


# Ubuntu Server

Ubuntu Server is a Linux distribution developed by Canonical Inc., noted for its stability and ease of use. You can find out more on [the Ubuntu Wiki](https://wiki.ubuntu.com/BionicBeaver/ReleaseNotes).

Almost all of the CSL runs on Ubuntu Server, except for [Workstations](/services/workstations) (which run Debian) and FreeIPA (which runs AlmaLinux).

## Notable Features

* Easy-to-use installer ISO
* Extremely large, if not *the* largest, package ecosystem
* Has included some unpopular software, including (but not limited to):
  1. The Unity desktop environment
  2. Integrated advertising
  3. netplan

## Notable CSL modifications

* Instead of installing from a usb, we prefer to use [Netboot](/technologies/networking/netboot).

## Trivia

* Ubuntu gets a significant portion of its packages from Debian, and shares the same package manager (`apt`).
* One of Ubuntu's official help channels is actually found on [StackExchange](https://askubuntu.com/).
* Ubuntu major releases are referred to by alliterating `<adjective> <animal>` codenames. As of this writing (Jan 2019), the current stable release (18.04.1) is codenamed **Bionic Beaver**.
* The default version of Python is currently 3 on all Ubuntu releases.
* `nano`is installed as the default text editor.
* Netplan can act as a configuration proxy for NetworkManager or systemd-networkd, in case you ever wanted to double the amount of cancer you handle.


# AlmaLinux

[AlmaLinux](https://almalinux.org) is a stable Linux distribution derived from the sources of the popular [RedHat Enterprise Linux](https://www.redhat.com/en/technologies/linux-platforms/enterprise-linux).

AlmaLinux is used for our FreeIPA servers because the Debian family doesn't offer the server packages (yet...)

## Notable Features

* It supports FreeIPA Server.

## Notable CSL Modifications

* We use [Netboot](/technologies/networking/netboot) to install it.

## Trivia

* AlmaLinux comes with a firewall set up by default, which is nice for security reasons given how critical our Alma machines are.&#x20;
* The AlmaLinux servers have automatic updates set up. They patch themselves at 3AM on weekends. We never have to do anything ourselves.


# Debian

Debian is a popular Linux operating system. It serves as the upstream distribution of Ubuntu and is used on all CSL workstations.

### Notable Features

* It allows you to launch Firefox. For some reason (probably related to Ubuntu/Canonical pushing their `snapd` package manager), Firefox wouldn't start on workstations after we migrated from AFS to NFS, and Mozilla's builds would get replaced by a stub for the Snap installer, which is absolutely infuriating.

### Notable CSL Modifications

* Unlike the other OSes, workstations are imaged with USBs instead of netboot.

### Trivia

* Debian releases are codenamed with Toy Story character names. The workstations use version 12, aka `bookworm`.


# Tools


# Ansible

**Ansible** is an automation tool that allows us to run scripts to configure services and devices across the lab. Our goal with Ansible is to have the ability to bring up every service by only running the ansible plays.

For the purposes of the Lab, "ansibilize" is a word that refers to making a set of systems operate under the control of Ansible plays completely.

To see more about how to use ansible, refer to this link: <https://docs.ansible.com/>

## Organization

In order to effectively use Ansible, you need to know it's vocabulary.

* **Hosts** are machines that Ansible can manage
* **Groups** are sets of hosts defined in the `hosts` file
* **Modules** contain a single thing for Ansible to do. There is a `file` module for doing file operations, an `apt` module for installing packages, a `shell` module for running shell commands, etc. All modules can be found at <https://docs.ansible.com/ansible/latest/modules/modules_by_category.html>.
* **Tasks** are a set of Modules to be run in order. Tasks can also include tasks from other files.
* **Roles** are assigned to Groups and contain a single entrypoint task at `roles/<role_name>/tasks/main.yml`. Each role can also contain its own files at `roles/<role_name>/files`, and ditto for templates.
* **Plays** define a set of Roles to apply to a set of Groups. Usually it's a many Role to one Group relationship per play.

All Ansible configuration files are written in [YAML](https://yaml.org/). The best way to learn YAML is by reading existing YAML files. It's structured a bit like JSON, only indentation based like Python. So instead of

```javascript
{"dictionary-key": ["list-value1", "list-value2"]}
```

you have

```yaml
dictionary-key:
  - list-value1
  - list-value2
```

## CSL's Role Management

There are two roles that should be applied to almost every machine: `common` and `auth`. `common` installs a good suite of common utilities, and `auth` allows the machine to have [Kerberos](/obsolete/kerberos) login. Other than that, we usually assign our roles on a per-group basis, although that isn't too modular. [AFS](/obsolete/afs) support has its own role, but unfortunately [CephFS](/technologies/storage/ceph/cephfs) doesn't yet.

## Running Ansible

First, you will want to install Ansible either by using your OS's package manager or `pip install ansible`.

Then, you should `cd` to the place you have cloned your Ansible repository, and run the following command:

```bash
ansible-playbook -i hosts --ask-vault-pass <target_play>.yml
```

{% hint style="warning" %}
Before ansible can be run on a remote host, the remote host must have python installed.
{% endhint %}

You will usually need access to the `ansible_vault` password in [Passcard](/technologies/authentication/passcard) before you can run any important plays, as a module in `auth` needs to access an encrypted file. For more `ansible-playbook` options, you should run `ansible-playbook --help`.

### Advanced usage

The Ansible plays for running the [Cluster](/services/cluster) are very complicated and take advantage of some cool things Ansible has to offer.

The first thing is the `when` directive, added to the end of any module, specifying when a module should be run. Just like in `common` and `auth`, different package managers with different packages names are used on different systems, but by only running `apt` when on [Ubuntu](/technologies/operating-systems/ubuntu-server) and `yum` when on [CentOS](/technologies/operating-systems/centos), we can account for that.

The other thing is the `--extra_vars` flag the `ansible-playbook` command. You can pass in a variable to make the play do a fresh install of all built-from-source packages, uninstall a previous version of a package, and I would say more but that's about it. You should read the play to figure out how that works.

## Trivia

* The Ansible is a fictional FTL communication device appearing in the *Ender's Game* series, used by aliens to manage their entire fleet


# Slack

Slack (<https://slack.com>) is a proprietary set of tools for team collaboration. It offers various integration with different services. We have a workspace at <https://tjcsl.slack.com>. The CSL's first widespread use of the Slack workspace began in August of 2018. Slack became the official form of communication under the direction of Omkar Kulkarni. It was replaced by Mattermost in December 2019 because Slack's free plan only allows for three months of message history and the school didn't want to pay for it.


# GitBook

GitBook is the documentation platform used by the Computer Systems Lab. It is the central hub of knowledge for the Lab and is hosted on [gitbook.com](https://gitbook.com), a proprietary platform.

## History

The CSL's GitBook came into existence after frustration with inadequate documentation on Livedoc. Initially began by Theo Ouzhinski in late August of 2018, GitBook now serves as the CSL's official documentation platform.

## Structure

GitBook, the website, allows the creation of a GitBook account via e-mail, GitHub, or Google. Every account can be a member of a different organizations which in turn have their own workspaces. Workspaces can be either publicly available or restricted.

The TJCSL organization contains the TJ CSL workspace which contains all of our public documentation for Sysadmins.

The official GitBook documentation can be found [here](https://docs.gitbook.com/).

## Access Control

The Lead Sysadmins, Faculty Sponsor, and Documentation Lead should be owners/admins of the TJCSL organization on GitBook. Other Sysadmins should have write access to the documentation on GitBook. The expectation is that you do not violate the trust that is given to you.

The Lead Sysadmins, Faculty Sponsor, and Documentation Lead should be admins of the `gitbook` repository on GitHub. At their discretion, they may grant write access to other Sysadmins, but there is always the option of relying on pull requests for contributions.

## Editing

Editing for GitBook can be done via a git repo or the visual editor. Changes to the organizational structure (adding pages, moving pages, removing pages, etc.) should generally be made through the online visual editor. Editing/adding to current documents can be done through Markdown. GitBook-specific features (page links, hints, tables) rely on custom solutions that cannot be easily done in Markdown. Hence, you should use the visual editor for creating/editing those features.

GitBook does a pretty good job at explaining their setup in their [docs](https://docs.gitbook.com).

## GitHub Integration

GitBook's GitHub integration allows editors to not only edit via the visual editor but through a git repo. Currently, the documentation's GitHub repository is located at <https://github.com/tjcsl/gitbook>. Pushes to the GitHub repo are mirrored to GitBook while published changes on GitBook are mirrored to GitHub. You can see the status of the sync at the bottom right of the editing screen: `GitHub syncing`. This sync can take up to one minute to complete. Generally, changes in reverse should be avoided to prevent conflicts.


# GitLab

**GitLab** is a MIT-licensed, web-based Git repository manager that provides issue tracking, code hosting, and Continuous Integration (CI)/Continuous Development (CD). The CSL uses GitLab to host Git repositories for the sysadmins (excluding the public repositories for [GitBook](/technologies/tools/gitbook), [Ion](/services/ion), [Director](/services/director), and [Othello](/services/academic-services/othello)). The website for the developers behind GitLab can be found at [gitlab.com](https://gitlab.com) and the CSL's self-hosted version can be found at [gitlab.tjhsst.edu](https://gitlab.tjhsst.edu).

## History

The first installation of GitLab occured around September of 2017. All the repositories previously on the [TJCSL Github](https://github.com/tjcsl) had to be manually marked deprecated and moved to the new system. It was reinstalled after the events of the [Cephpocalypse](/machines/history/2018-cephpocalypse) during October of 2018.

## Primary Uses

* Hosting repositories (for passcard, ansible, dns, dhcp, qemuconfig, etc.)
* Providing CI pipelines for updates to [DNS](/technologies/networking/dns) and [DHCP](/technologies/networking/dhcp).


# Setup

## Setting up GitLab

### Installing GitLab

#### Ansible Installation

After running Ansible, note that the current play does not contain settings for SMTP. To set up SMTP, in `/etc/gitlab/gitlab.rb`, find the following configuration settings, uncomment the lines and set their values to the ones below:

```
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "mail.tjhsst.edu"
gitlab_rails['smtp_port'] = 22
```

After saving these settings to `gitlab.rb`, apply these settings using `gitlab-ctl reconfigure`.

#### Manual Installation

{% hint style="danger" %}
In this method, **never** execute `gitlab-ctl reconfigure` unless specifically stated to.
{% endhint %}

Manual setup can be found on GitLab's website [here](https://about.gitlab.com/installation/). However, the only commands you need to run successively are as follows:

```
sudo apt-get update
sudo apt-get install -y curl openssh-server ca-certificates
sudo apt-get install -y postfix
curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.deb.sh | sudo bash
sudo EXTERNAL_URL="http://gitlab.tjhsst.edu" apt-get install gitlab-ee
```

After running these commands, head to `/etc/gitlab/`

1. Locate `gitlab.rb` in the ansible repository under `roles/gitlab/files`
2. In `/etc/gitlab` execute`sudo mv gitlab.rb gitlab-OLD.rb`
3. Copy the Ansible version of `gitlab.rb` into `/etc/gitlab`.

### Initial Configuration

{% hint style="warning" %}
Make sure you ran `gitlab-ctl reconfigure` after editing `gitlab.rb`as instructed in previous steps to apply all changes. This usually takes 30 seconds to 3 minutes depending on the settings.
{% endhint %}

#### Initial Login

After initial setup, log in using the Standard option as `root`, with the default GitLab password. Immediately change this to a more secure password in line with CSL standards.

#### Removing Standard and Sign-Up options

On initial login, note how there were three possible options: LDAP, Standard, and Sign-Up. As we do not use the Standard and Sign-Up options, it is necessary to remove them by following the steps below:

1. Head to the Admin Options, an icon depicting a wrench links here
2. On the left sidebar, find the Settings option and open the page.
3. Locate the respective check boxes under the Sign-up and Sign-in drop-downs.

{% hint style="info" %}
The exact naming of the drop-downs and check-boxes are omitted as they have historically changed with versions.
{% endhint %}

{% hint style="success" %}
When Standard and Sign-Up are missing from the login page leaving LDAP, configuration is done.
{% endhint %}


# Updating

GitLab releases updates to its Enterprise Edition software very regularly.  A major upgrade is always released the 22nd of every month.

{% hint style="warning" %}
Please keep in mind the CSL[ upgrade guidelines](/policies/upgrade-policy) for production systems when deciding whether to upgrade GitLab.  When in doubt, ask someone more experienced and BACKUP DATA.
{% endhint %}

To perform an upgrade,

{% hint style="info" %}
During an `apt upgrade`, GitLab performs a backup of the SQL database.
{% endhint %}

* Schedule a maintenance period
* Perform a backup of data either via a Ceph snapshot or gitlab-rake

  * gitlab-rake:

  As root on `gitlab`, run

  ```bash
  gitlab-rake gitlab:backup:create STRATEGY=copy
  ```

  to backup all repositories to /var/opt/gitlab/backups

  * Ceph snapshot:

  As root on a Ceph monitor, run the following to perform a snapshot of the Ceph image

  ```bash
  rbd snap create virtual-machines/gitlab@<SNAPSHOT NAME>
  ```
* Run the following to upgrade GitLab

```
apt update && apt upgrade -y
```

* The above upgrade will take time to perform.  When the upgrade finishes, it should give you a success message.  After the upgrade successfully completes, it will take a few minutes for all workers to start up so in that time frame you may see a 502 when accessing the site. &#x20;

{% hint style="info" %}
LDAP login may temporarily not work in the minutes after a login. ***This is fine.*** If more than 15 minutes have passed and GitLab is not working, perform debugging to fix the problem or rollback the upgrade as per the GitLab docs.
{% endhint %}


# Virtualization


# QEMU/KVM


# Libvirt


# Advanced Computing


# MPI

We don't really use **MPI** for any day-to-day tasks in the CSL, but it's important to know how it works to support some of the high-powered Senior Research projects going on [The Cluster](/services/cluster) and Parallel Computing labs.

## Example MPI Program

Copied from a tutorial somewhere.

```c
// hello_mpi_world.c
#include <mpi.h>
#include <stdio.h>

int main(int argc, char** argv) {
    // Initialize the MPI environment
    MPI_Init(NULL, NULL);

    // Get the number of processes
    int world_size;
    MPI_Comm_size(MPI_COMM_WORLD, &world_size);

    // Get the rank of the process
    int world_rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);

    // Get the name of the processor
    char processor_name[MPI_MAX_PROCESSOR_NAME];
    int name_len;
    MPI_Get_processor_name(processor_name, &name_len);

        // Print off a hello world message
        printf("Hello world from processor %s, rank %d out of %d processors\n",
               processor_name, world_rank, world_size);

        // Finalize the MPI environment.
        MPI_Finalize();
    }
```

Then, compile with `mpicc --std=c99 hello_mpi_world.c -o hello_mpi_world` And run with [Slurm](/services/cluster/slurm) using `srun -N4 ./hello_mpi_world` (Or locally using `mpirun -n4 ./hello_mpi_world`)

## What MPI software we use

* **PMIX 2.2.2**
* **OpenMPI 3.1.3**

See the relevant [Ansible](/technologies/tools/ansible) plays in [Cluster Administration](/services/cluster/administration) for more details on how it is installed.


# Tensorflow

**Tensorflow** is a powerful compute-graph based software allowing high-performance neural networks to be constructed in Python. It's specific strength is in seamless GPU execution.

## Which Machines

* [ASM](/machines/other/asm)
* [Duke](/machines/other/duke)
* [Snowy](/machines/other/snowy)
* [Zoidberg](/machines/hpc-cluster/zoidberg)
* GPU-enabled nodes in the [Borg Cluster](/machines/borg-cluster)

Only Duke and Zoidberg are publicly accessible. For the rest of the machines, you must either use [Slurm](/services/cluster/slurm) (for the Borg Cluster) or get a custom login from the Sysadmin in charge of the machine.

## Example Program

```python
'''
A linear regression learning algorithm example using TensorFlow library.
Author: Aymeric Damien
Project: https://github.com/aymericdamien/TensorFlow-Examples/
'''

from __future__ import print_function

import tensorflow as tf
import numpy
import matplotlib.pyplot as plt
rng = numpy.random

# Parameters
learning_rate = 0.01
training_epochs = 1000
display_step = 50

# Training Data
train_X = numpy.asarray([3.3,4.4,5.5,6.71,6.93,4.168,9.779,6.182,7.59,2.167,
                         7.042,10.791,5.313,7.997,5.654,9.27,3.1])
train_Y = numpy.asarray([1.7,2.76,2.09,3.19,1.694,1.573,3.366,2.596,2.53,1.221,
                         2.827,3.465,1.65,2.904,2.42,2.94,1.3])
n_samples = train_X.shape[0]

# tf Graph Input
X = tf.placeholder("float")
Y = tf.placeholder("float")

# Set model weights
W = tf.Variable(rng.randn(), name="weight")
b = tf.Variable(rng.randn(), name="bias")

# Construct a linear model
pred = tf.add(tf.multiply(X, W), b)

# Mean squared error
cost = tf.reduce_sum(tf.pow(pred-Y, 2))/(2*n_samples)
# Gradient descent
#  Note, minimize() knows to modify W and b because Variable objects are trainable=True by default
optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)

# Initialize the variables (i.e. assign their default value)
init = tf.global_variables_initializer()

# Start training
with tf.Session() as sess:

    # Run the initializer
    sess.run(init)

    # Fit all training data
    for epoch in range(training_epochs):
        for (x, y) in zip(train_X, train_Y):
            sess.run(optimizer, feed_dict={X: x, Y: y})

        # Display logs per epoch step
        if (epoch+1) % display_step == 0:
            c = sess.run(cost, feed_dict={X: train_X, Y:train_Y})
            print("Epoch:", '%04d' % (epoch+1), "cost=", "{:.9f}".format(c), \
                "W=", sess.run(W), "b=", sess.run(b))

    print("Optimization Finished!")
    training_cost = sess.run(cost, feed_dict={X: train_X, Y: train_Y})
    print("Training cost=", training_cost, "W=", sess.run(W), "b=", sess.run(b), '\n')

    # Graphic display
    plt.plot(train_X, train_Y, 'ro', label='Original data')
    plt.plot(train_X, sess.run(W) * train_X + sess.run(b), label='Fitted line')
    plt.legend()
    plt.show()

    # Testing example, as requested (Issue #2)
    test_X = numpy.asarray([6.83, 4.668, 8.9, 7.91, 5.7, 8.7, 3.1, 2.1])
    test_Y = numpy.asarray([1.84, 2.273, 3.2, 2.831, 2.92, 3.24, 1.35, 1.03])

    print("Testing... (Mean square loss Comparison)")
    testing_cost = sess.run(
        tf.reduce_sum(tf.pow(pred - Y, 2)) / (2 * test_X.shape[0]),
        feed_dict={X: test_X, Y: test_Y})  # same function as cost above
    print("Testing cost=", testing_cost)
    print("Absolute mean square loss difference:", abs(
        training_cost - testing_cost))

    plt.plot(test_X, test_Y, 'bo', label='Testing data')
    plt.plot(train_X, sess.run(W) * train_X + sess.run(b), label='Fitted line')
    plt.legend()
    plt.show()
```


# Networking

## The OSI Layer System

There is lots and lots of stuff here, but it's covered more succinctly and completely on [Wikipedia](http://en.wikipedia.org/wiki/OSI_model). However this will be left here since it is generally more applicable to the Systems Lab.

It is easiest to look at the network as a layer system, where each layer sits on top of the previous layer and uses its functions. This can also be compared to the level system presented in the computer architecture course.

### Layer 1

The first network layer is the "hardware," which in this case is the cable. There are a few different types of cable that can handle network connections, but below are the more commmon ones. (BTW, you can get a lot of this information from Phrack.)

#### Category 3 UTP

This is the old standard for cable. In actuality, there is nearly no such cabling in the school. Cat 3 can handle up to a 10Mbps link, which is the reason it is so unattractive.

#### Category 5 UTP

Currently this is the worldwide standard for LAN wiring. Cat 5 cable can handle up to 100Mbps if all eight wires are connected correctly. There is also a Cat 5e standard that exists, which supposedly handles up to 1Gbps (350MHz). When making such cables, one has to be careful for the cables to meet the Cat 5 restrictions. They have to be between 3 feet and 100 meters. Also, the specification only allows for the untwisting of 1/2 inch of cable on each end.

#### Fiber

Fiber optic cable can carry data for longer distances than Cat 5. The standard fiber cable can be as long as 2 kilometers. Fiber can also handle Gigabyte connections quite well. Unfortunately fiber optic cable is very expensive, and rarely used in LAN settings.

### Layer 2

Layer 2 is the transport layer. Basically, it defines the way the data moves through the Layer 1 network (i.e. the cable). There are a number of protocols to do that.

#### Ethernet

Ethernet is one of the most commonly used layers. According to the Ethernet standard, RFC826, each NIC (Network Interface Card) must have a unique MAC address. A MAC address is a unique 48-bit number given to every piece of Ethernet networking equipment. The first 24 bits of it were given out to manufacturers. The last 24 bits are up to each manufacturer's discretion. Although it is possible to change the MAC address on a board, I wouldn't recommend it, as there is no need for it, and it can cause major havoc. Each Ethernet "packet" is called a frame. Each Ethernet frame contains the source MAC address, the destination MAC address, and the payload (also called MTU), which can be up to 1500 bytes. (If you are using copper gigabit Ethernet, some switches may let you to set the MTU to 9000, but that is outside the standard.) The higher layers are carried in these 1500 bytes.

#### ATM

ATM allows for up to 155Mbps transfer speeds, but has a smaller MTU than Ethernet. On the other hand, ATM provides some of the features that higher levels provide, such as guaranteed data delivery, and thus is an overall gain for applications such as video streaming. It is, however, little used.

### Layer 3

Layer 3 is generally referred to as the IP layer. This is the layer that allows computers to communicate with one another using a certain address scheme that is not interface dependent (i.e. MAC address).

#### IPv4

IPv4 is the current overall standard used on the Internet. Addresses are usually shown with dotted quads (like 198.38.16.9). This addressing scheme thus allows 255^4 different addresses. This IP space is split into three different classes of IP blocks, which are designated A, B, and C. Class A is the 255.0.0.0 netmask, meaning that only the first of the quads is specified. For example, MIT has the 18 class A. Class B has a 255.255.0.0 netmask, meaning that the first two quads are specified. Fairfax County has the 151.188 class B. Class C has a 255.255.255.0 netmask, and thus includes only 256 IPs. For example, the Computer Systems Lab owns 16 Class C's: 198.38.16 - 198.38.31. The body that gives these IP blocks out is arin.net. In addition to all that, there are a few IP's that are reserved for special purposes. The 10 Class A is reserved for local networks, as well as the 192.168 Class B. The 127 Class A is reserved for loopback networks. All Class A's 224 and above are reserved for multicast and other similar applications.

#### Subnets

Since it is impractical to have each and every computer on the same physical network, subnets were created. Each subnet is defined by a netmask, which says how many computers there are on the subnet. For example, if a computer's IP is 198.38.17.1 and its netmask is 255.255.248.0, it can expect 198.38.16-23 to be in its local network. The way it would determine that is that if its IP and the destination IP when AND'ed with the netmask come out to the same thing, that would mean that they are on the same physical network.

#### ARP

ARP (Address Request Protocol) is the protocol used to figure out what IP maps to what MAC address. This protocol really does not belong in the layer system, and neither does ICMP. The way it works is that an ARP packet is sent out which says something to the effect of "I'm looking for the MAC address that holds the IP xxx.xxx.xxx.xxx" (this packet is broadcast). After this, when the requesting computer finds out the correct MAC address, it can start sending proper Ethernet frames to it.

#### IPX

IPX is an alternative to IP made by Novell. The way its addressing is done is that each node's IPX address is based on the MAC address of the NIC. In order for IPX to work, the router connecting two segments has to know about IPX and be able to forward it. Since IP became the mainstream standard, and most routers on the Internet do not forward IPX packets, it can only be used in a LAN setting.

### Layer 4

Layer 4 refers to the layer that is set on top of the IP/IPX layer.

#### ICMP

ICMP (Internet Control Message Protocol) is a port-less protocol which is most commonly used for two things: ICMP Echo (aka ping), and traceroute. Other than that, it's useless. For now, the workings of traceroute are black magic, unless you feel like figuring out its code (the beauty of Open Source).

#### TCP

There is a book about TCP, called \[TCP/IP Illustrated], which is in two volumes, each of about 1000 pages. Thus, I will only try to make important points about TCP rather than describe it in the fullest possible way. TCP allows for direct connections between two IPs. Moreover, it guarantees that the data that leaves from one end gets to the other. It does this by using rather complex sequencing, and acknowledgment, which is beyond the scope of this document. With TCP you can have multiple ports per IP, and there are POSIX functions in Linux which will let you bind(2) to those ports and listen(2) on them in order to accept(2) incoming connections. This is all done through the socket(2) interface. To read more about these system calls, one can look up each of the previously referred to man pages.

#### UDP

UDP is the same thing as TCP, only it in no way guarantees delivery. This is usually not a problem on a local network, but when sending packets over the Internet, it is not uncommon to lose a few here and there. One advantage of UDP is that it can be used to multicast packets. This means that one and the same UDP packet will be broadcast to all nodes on a local network. This can facilitate large, repetitive data transfers. One obvious application of this is video broadcast, where one video server would multicast the video stream. Multicast uses a special set of IPs, 224. and above.

## Switching

The difference between a hub and a switch is that a hub just forwards all incoming traffic to all of its ports. As such, all computers that sit directly on a hub can listen to any traffic that goes through that hub. In addition to being inefficient, this allows for the possibility of a NIC to go into promiscuous mode and pass all of that traffic to the user. (Under regular conditions, NICs throw out all traffic not destined for their MAC address. In promiscuous mode, they take in all traffic.) A switch is smarter than that. It looks at the incoming traffic, and routes it directly to certain ports depending on the contents of that traffic. Switching can be done on multiple layers.

### Layer 2

Layer 2 switching is the most common type of switching that all switches can do. These switches figure out what MAC addresses sit on which ports, and as such, they provide direct port to port paths for communication. Their traffic will not be "overheard" by any other ports. (Of course if you have a really nice switch, then you can set monitoring ports which will be able to hear all or some traffic.) In addition to this layer of security, switches allow ports of different speeds to be connected. They achieve this by having a relatively large packet buffer sitting on each port which can store some data. Switches also allow for Full Duplex operation. This means that computers can send out packets all at the same time without them colliding. Collisions arise from having multiple interfaces send a packet at the same time. However this is avoided as the switch allows each port to see only the traffic which relates to it. Collisions can be a real problem with hubs especially, since it means that no computer sitting on a hub can send a packet while another is sending.

### Layer 3/4

Layer 3/4 switches take switching to the TCP/IP, UDP/IP, and IPX levels. These switches can take instructions such as "All IPs in this range go to this port" or "TCP port 80 of this IP goes to this port, while TCP port 21 on that IP should not go through at all." This is very similar to what routers do, and in fact is the same.

## Routing

Routers are basically more versatile layer 3/4 switches. Most routers can handle a very large variety of inputs. For example, most low-end routers will have a 10BT and FDDI ports. FDDI is used for T1-type connections and is never seen on a switch. Routers can also handle such inputs as OC-12 and above. Some switches can handle an OC-12 input (Gigabit), but there are no switches that can handle a dozen OC-148 connections (10 Gigabit apiece). In general, routers are used to "convert" between different types of mediums (and route traffic through them), while switches are used to connect many machines together.

### Purpose

The purpose of routing may not seem obvious. The question arises, "Why not put all computers onto the same physical layer 2 network?" The answer is, "Try it." Ignoring the different connection type issue, let's do the math for the Internet, which is nothing more than a big network. If there are a meager 6,000,000 computers on the Internet all connected to each other through 100Mbps connections (and a whole bunch of switches), then let us take a look at some of the procedures. For example, let us look at a simple broadcast packet that is used very often: ARP. When a computer sends out an ARP packet, then all other computers in the entire world will receive that ARP and one will respond. So at maybe an average of 1 ARP/minute/computer, each being 64 bytes, we get 6.1MB/s of sustained traffic over the whole network taken up by just ARP traffic. Another theoretical 6MB/s are left for all other communication. (What if there are 60,000,000 computers?) Or in a different situation, let's say there's one person who thinks, "Let's see what happens if I send out broadcast packets at the full 100Mbit/s." Now, these broadcast packets get sent to each and every computer. That would mean that just this one person is taking up all bandwidth available. Needless to say, there needs to be a better way of doing this.

### Overview

Most routers have a connection to the inside world and the outside world. With only two connections, its job is simple: relaying packets back and forth between interfaces, dropping broadcast and multicast packets. The routers also usually will take a look at the traffic that goes in and out, blocking some of the traffic and redirecting the other portion. For example, it is usually a good idea to block unnecessary ports to the outside world to prevent an attack. A router would take care of that.

### ARP Proxying

ARP Proxying is used when two separate network segments exist, but need to be united into one. Thus, the router in between them will proxy the ARP requests between both segments, effectually making the nodes appear to be on the same segment. We used to do this for the soundlab in order to avoid any complications. However this is a very hack-ish way of setting things up, and should very rarely be used. It is usually better to resolve conflicts in other ways.

### IPchains and IPtables

These are the tools that allow you to use filtering/forwarding features of the Linux kernel. ipchains is for 2.2 (though 2.4 also has compatibility options for it), while iptables is for 2.4 kernels. These are mainly used in two situations: for NAT (aka IP Masquerading), and routing. Take a look at the HOWTOs provided on [The Linux Documentation Project](http://www.tldp.org) with respect to both of those tools.

## VLANs

Some switches just have too many ports, and you would like to use one switch for multiple physical networks which you do not want to be connected together. VLANs allow you to split up a single physical connected network into logical segments, and disallow communications between the segments.

### Cluster

The new cluster is a good example of the use of a VLAN. The machines must talk amongst themselves to relay information, but outside machines should not be able to intercept them or be able to directly communicate with them. Traffic is only allowed through a few machines that are connected to both the cluster VLAN and to the main VLAN in the lab.

## Notes

Most of the text in this page was taken from [The Syslab Book](https://livedoc.tjhsst.edu/wiki/The_Syslab_Book), with slight alterations.


# Netbox

Netbox is an [open-source](https://github.com/netbox-community/netbox/) Django application that is designed to help manage and document networks and the devices on those networks. In the CSL we use it to document each machine and VM along with their network configurations.

## Installation&#x20;

Netbox consists of 4 parts:

1. PostgreSQL database
2. Redis
3. Netbox Django Application
4. HTTP Proxy and Daemon

Basic installation instructions are [here](https://netbox.readthedocs.io/en/stable/installation/). \
The `netbox` Ansible playbook properly installs and configures everything as well.

### Upgrading Netbox

Netbox graciously created an upgrade script that automatically upgrades the current installation.\
Just `ssh` into `netbox` and run the following:

```bash
/opt/netbox/upgrade.sh
```

Once the script finishes, make sure to restart the `supervisor`daemons:

```
supervisorctl restart netbox
supervisorctl restart netbox-rqworker
```

## Using Netbox

You can access the netbox web page at <https://netbox.tjhsst.edu>, but you MUST be VPN'ed into the CSL in order to access the website.

### Creating User Accounts

Netbox has SSO support. Use that to log in.

### Interacting with Netbox

Using netbox is pretty straightforward; navigating through the web page is pretty intuitive. More specific documentation on netbox is available [here](https://netbox.readthedocs.io/en/stable/core-functionality/ipam/), but here are a few basics:

* The highest order of organization is a `region`, it represents the physical area where the network is (TJHSST , CSL).&#x20;
* Next there are `sites`, they represent the specific area in the `region` that divides the network (Machine Room, Room 200, Room 200C, etc.).&#x20;
* Each `site` can have `racks`, which represent a physical server rack (only used in the Machine Room `site`)
* `devices` are the next organizational unit. `devices` are NOT VMs. `devices` can belong to a `rack`(in the case of servers), or they can be independent (in the case of workstations).
* `devices` have `interfaces` which can be assigned an `ip`.&#x20;
  * Creating `interfaces` and `ips` is not obvious, though.
    1. &#x20;First you have to create a `device`
    2. then on that `device`'s overview page, click the "Add Components" dropdown and select "Interfaces".
    3. &#x20;Then fill out the information for that `interface`.&#x20;
    4. Finally, when the `interface` is created, scroll to the bottom of the `device`'s overview page and click the green "+" box and add an `ip` there.

It is **much** easier to mass create devices through netbox's API, available at <https://netbox.tjhsst.edu/api>.\
In order to use the API, however, you must first create an API token [here](https://netbox.tjhsst.edu/user/api-tokens/).<br>

Some (messy) scripts that were used to bulk create the `borg` devices and workstations are available at <https://gitlab.tjhsst.edu/sysadmins/docs/netbox-scripts.git>




---

[Next Page](/llms-full.txt/1)

