Compare commits

...

3 commits

8 changed files with 1288 additions and 7 deletions

View file

@ -4,8 +4,29 @@ import sitemap from '@astrojs/sitemap';
//import cloudflare from "@astrojs/cloudflare";
import remarkGfm from "remark-gfm";
import remarkRehype from "remark-rehype";
import rehypePrettyCode from "rehype-pretty-code";
import json from "./public/themes/github_light.json" assert { type: "json" };
import tailwind from "@astrojs/tailwind";
const options = {
// Specify the theme to use or a custom theme json, in our case
// it will be a moonlight-II theme from
// https://github.com/atomiks/moonlight-vscode-theme/blob/master/src/moonlight-ii.json
theme: json,
// Callbacks to customize the output of the nodes
onVisitLine(node) {
// Prevent lines from collapsing in `display: grid` mode, and
// allow empty lines to be copy/pasted
if (node.children.length === 0) {
node.children = [{type: 'text', value: ' '}];
}
},
onVisitHighlightedLine(node) {
// Adding a class to the highlighted line
node.properties.className.push('highlighted');
},
};
// https://astro.build/config
export default defineConfig({
site: 'https://dev.noway.moe',
@ -17,10 +38,23 @@ export default defineConfig({
inlineStylesheets: "auto",
},
markdown: {
gfm: true,
syntaxHighlight: false,
remarkPlugins: [
remarkGfm,
[remarkRehype, { clobberPrefix: "" }],
[rehypePrettyCode, options],
],
gfm: true,
//shikiConfig: {
// // Choose from Shiki's built-in themes (or add your own)
// // https://github.com/shikijs/shiki/blob/main/docs/themes.md
// theme: 'dracula',
// // Add custom languages
// // Note: Shiki has countless langs built-in, including .astro!
// // https://github.com/shikijs/shiki/blob/main/docs/languages.md
// langs: ["c", "ssh-config"],
// // Enable word wrap to prevent horizontal scrolling
// wrap: true,
//},
}
});

102
package-lock.json generated
View file

@ -13,9 +13,11 @@
"@astrojs/sitemap": "^3.0.3",
"@astrojs/tailwind": "^5.0.4",
"astro": "^4.0.7",
"rehype-pretty-code": "^0.12.3",
"remark-gfm": "^4.0.0",
"remark-rehype": "^11.0.0",
"sharp": "^0.33.1",
"shiki": "^0.14.7",
"tailwindcss": "^3.4.0"
},
"devDependencies": {
@ -76,6 +78,14 @@
"vfile": "^6.0.1"
}
},
"node_modules/@astrojs/markdown-remark/node_modules/shikiji": {
"version": "0.6.13",
"resolved": "https://registry.npmjs.org/shikiji/-/shikiji-0.6.13.tgz",
"integrity": "sha512-4T7X39csvhT0p7GDnq9vysWddf2b6BeioiN3Ymhnt3xcy9tXmDcnsEFVxX18Z4YcQgEE/w48dLJ4pPPUcG9KkA==",
"dependencies": {
"hast-util-to-html": "^9.0.0"
}
},
"node_modules/@astrojs/mdx": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/@astrojs/mdx/-/mdx-2.0.2.tgz",
@ -1906,6 +1916,11 @@
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
"node_modules/ansi-sequence-parser": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz",
"integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg=="
},
"node_modules/ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
@ -2071,6 +2086,14 @@
"url": "https://opencollective.com/libvips"
}
},
"node_modules/astro/node_modules/shikiji": {
"version": "0.6.13",
"resolved": "https://registry.npmjs.org/shikiji/-/shikiji-0.6.13.tgz",
"integrity": "sha512-4T7X39csvhT0p7GDnq9vysWddf2b6BeioiN3Ymhnt3xcy9tXmDcnsEFVxX18Z4YcQgEE/w48dLJ4pPPUcG9KkA==",
"dependencies": {
"hast-util-to-html": "^9.0.0"
}
},
"node_modules/autoprefixer": {
"version": "10.4.16",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.16.tgz",
@ -3479,6 +3502,18 @@
"url": "https://opencollective.com/unified"
}
},
"node_modules/hast-util-to-string": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.0.tgz",
"integrity": "sha512-OGkAxX1Ua3cbcW6EJ5pT/tslVb90uViVkcJ4ZZIMW/R33DX/AkcJcRrPebPwJkHYwlDHXz4aIwvAAaAdtrACFA==",
"dependencies": {
"@types/hast": "^3.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/hast-util-whitespace": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz",
@ -3886,6 +3921,11 @@
"node": ">=6"
}
},
"node_modules/jsonc-parser": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz",
"integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w=="
},
"node_modules/kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
@ -5484,6 +5524,11 @@
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/parse-numeric-range": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz",
"integrity": "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ=="
},
"node_modules/parse5": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
@ -6062,6 +6107,25 @@
"url": "https://opencollective.com/unified"
}
},
"node_modules/rehype-pretty-code": {
"version": "0.12.3",
"resolved": "https://registry.npmjs.org/rehype-pretty-code/-/rehype-pretty-code-0.12.3.tgz",
"integrity": "sha512-6NbIit8A3hLrkKBEbNs862jVnTLeIOM2AmM0VZ/MtyHb+OuNMeCa6UZSx6UG4zrobm5tY9efTwhih1exsGYsiw==",
"dependencies": {
"@types/hast": "^3.0.3",
"hast-util-to-string": "^3.0.0",
"parse-numeric-range": "^1.3.0",
"rehype-parse": "^9.0.0",
"unified": "^11.0.4",
"unist-util-visit": "^5.0.0"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"shikiji": "^0.7.0 || ^0.8.0 || ^0.9.0"
}
},
"node_modules/rehype-raw": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz",
@ -6896,14 +6960,32 @@
"node": ">=8"
}
},
"node_modules/shikiji": {
"version": "0.6.13",
"resolved": "https://registry.npmjs.org/shikiji/-/shikiji-0.6.13.tgz",
"integrity": "sha512-4T7X39csvhT0p7GDnq9vysWddf2b6BeioiN3Ymhnt3xcy9tXmDcnsEFVxX18Z4YcQgEE/w48dLJ4pPPUcG9KkA==",
"node_modules/shiki": {
"version": "0.14.7",
"resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.7.tgz",
"integrity": "sha512-dNPAPrxSc87ua2sKJ3H5dQ/6ZaY8RNnaAqK+t0eG7p0Soi2ydiqbGOTaZCqaYvA/uZYfS1LJnemt3Q+mSfcPCg==",
"dependencies": {
"hast-util-to-html": "^9.0.0"
"ansi-sequence-parser": "^1.1.0",
"jsonc-parser": "^3.2.0",
"vscode-oniguruma": "^1.7.0",
"vscode-textmate": "^8.0.0"
}
},
"node_modules/shikiji": {
"version": "0.9.12",
"resolved": "https://registry.npmjs.org/shikiji/-/shikiji-0.9.12.tgz",
"integrity": "sha512-jYbulSGcPKYKu2uFZOSg4lgrF7s9s8/ITFzRvczE6633wypMjnnTcRnG/mCFe6v1Dbov7bRCMsXVINBUD2FV9w==",
"peer": true,
"dependencies": {
"shikiji-core": "0.9.12"
}
},
"node_modules/shikiji-core": {
"version": "0.9.12",
"resolved": "https://registry.npmjs.org/shikiji-core/-/shikiji-core-0.9.12.tgz",
"integrity": "sha512-AYsAtsbZuq0FPT3mdskNMa+yxD5VwXrFC2sH7R2ELmncVGNYvSzR6Zlfq8iEzINq7/kKL5prtt81UFzFWTTbxQ==",
"peer": true
},
"node_modules/signal-exit": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
@ -7812,6 +7894,16 @@
}
}
},
"node_modules/vscode-oniguruma": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz",
"integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA=="
},
"node_modules/vscode-textmate": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz",
"integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg=="
},
"node_modules/web-namespaces": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz",

View file

@ -17,9 +17,11 @@
"@astrojs/sitemap": "^3.0.3",
"@astrojs/tailwind": "^5.0.4",
"astro": "^4.0.7",
"rehype-pretty-code": "^0.12.3",
"remark-gfm": "^4.0.0",
"remark-rehype": "^11.0.0",
"sharp": "^0.33.1",
"shiki": "^0.14.7",
"tailwindcss": "^3.4.0"
},
"devDependencies": {

View file

@ -0,0 +1,555 @@
{
"name": "Github Light Theme",
"type": "light",
"colors": {
"focusBorder": "#ffffff00",
"foreground": "#000000",
"editor.background": "#f6f6f6",
"editor.foreground": "#000000",
"scrollbar.shadow": "#ffffff",
"activityBar.border": "#ffffff",
"activityBar.background": "#ffffff",
"activityBar.foreground": "#000000",
"activityBarBadge.background": "#d73a49",
"statusBar.border": "#ffffff",
"statusBar.background": "#ffffff",
"statusBar.foreground": "#000000",
"statusBar.noFolderBackground": "#ffffff",
"statusBar.noFolderForeground": "#000000",
"statusBar.debuggingBackground": "#ffffff",
"statusBar.debuggingForeground": "#000000",
"editorGroup.border": "#ffffff",
"editorGroupHeader.tabsBackground": "#ffffff",
"editorGroupHeader.noTabsBackground": "#ffffff",
"editorGroupHeader.tabsBorder": "#ffffff",
"tab.activeBackground": "#ffffff",
"tab.inactiveBackground": "#ffffff",
"tab.border": "#ffffff",
"tab.activeBorder": "#d73a49",
"sideBar.border": "#ffffff",
"sideBar.background": "#ffffff",
"sideBar.foreground": "#000000",
"sideBarSectionHeader.background": "#ffffff",
"list.highlightForeground": "#d73a49",
"list.activeSelectionBackground": "#eeeeee",
"list.activeSelectionForeground": "#d73a49",
"list.inactiveSelectionBackground": "#eeeeee",
"list.inactiveSelectionForeground": "#d73a49",
"list.hoverBackground": "#eeeeee",
"list.hoverForeground": "#d73a49",
"list.focusBackground": "#eeeeee",
"list.focusForeground": "#d73a49",
"editor.lineHighlightBackground": "#fffbdf",
"editor.lineHighlightBorder": "#fffbdf",
"editorLineNumber.foreground": "#babbbc",
"editorLineNumber.activeForeground": "#000000",
"editor.selectionBackground": "#fed442",
"input.border": "#b2b2b2",
"input.background": "#ffffff",
"inputOption.activeBorder": "#000000",
"inputOption.activeForeground": "#000000",
"dropdown.border": "#b2b2b2",
"dropdown.background": "#ffffff",
"dropdown.listBackground": "#ffffff",
"notificationCenter.border": "#ffffff",
"notificationCenterHeader.background": "#ffffff",
"notificationToast.border": "#ffffff",
"notifications.background": "#ffffff",
"notifications.border": "#ffffff",
"button.background": "#d73a49",
"button.foreground": "#ffffff",
"titleBar.border": "#ffffff",
"titleBar.activeBackground": "#ffffff",
"titleBar.activeForeground": "#000000",
"titleBar.inactiveBackground": "#ffffff",
"titleBar.inactiveForeground": "#000000",
"editorWidget.background": "#eee",
"editorWidget.border": "#000000",
"editorSuggestWidget.highlightForeground": "#d73a49",
"editorSuggestWidget.selectedBackground": "#f0f0f0",
"panel.border": "#d73a49"
},
"tokenColors": [
{
"scope": [
"comment",
"punctuation.definition.comment",
"string.comment"
],
"settings": {
"foreground": "#6a737d"
},
"name": "Comment"
},
{
"scope": [
"constant",
"entity.name.constant",
"variable.other.constant",
"variable.language"
],
"settings": {
"foreground": "#005cc5"
},
"name": "Constant"
},
{
"scope": [
"keyword.operator.symbole",
"keyword.other.mark"
],
"name": "Clojure workaround; don't highlight these separately from their enclosing scope",
"settings": {
"foreground": "#000000"
}
},
{
"scope": [
"entity",
"entity.name"
],
"settings": {
"foreground": "#6f42c1"
},
"name": "Entity"
},
{
"scope": [
"variable.parameter.function"
],
"settings": {
"foreground": "#000000"
}
},
{
"scope": [
"entity.name.tag"
],
"settings": {
"foreground": "#22863a"
}
},
{
"scope": [
"keyword"
],
"settings": {
"foreground": "#d73a49"
},
"name": "Keyword"
},
{
"scope": [
"storage",
"storage.type"
],
"settings": {
"foreground": "#d73a49"
},
"name": "Storage"
},
{
"scope": [
"storage.modifier.package",
"storage.modifier.import",
"storage.type.java"
],
"settings": {
"foreground": "#000000"
}
},
{
"scope": [
"string",
"punctuation.definition.string",
"string punctuation.section.embedded source"
],
"settings": {
"foreground": "#032f62"
},
"name": "String"
},
{
"name": "Ada workaround; don't highlight imports as strings",
"scope": [
"string.unquoted.import.ada"
],
"settings": {}
},
{
"scope": [
"support"
],
"settings": {
"foreground": "#005cc5"
},
"name": "Support"
},
{
"scope": [
"meta.property-name"
],
"settings": {
"foreground": "#005cc5"
}
},
{
"scope": [
"variable"
],
"settings": {
"foreground": "#e36209"
},
"name": "Variable"
},
{
"scope": [
"variable.other"
],
"settings": {
"foreground": "#000000"
}
},
{
"scope": [
"invalid.broken"
],
"settings": {
"fontStyle": "bold italic underline",
"foreground": "#b31d28"
},
"name": "Invalid - Broken"
},
{
"scope": [
"invalid.deprecated"
],
"settings": {
"fontStyle": "bold italic underline",
"foreground": "#b31d28"
},
"name": "Invalid Deprecated"
},
{
"scope": [
"invalid.illegal"
],
"settings": {
"fontStyle": "italic underline",
"foreground": "#b31d28"
},
"name": "Invalid Illegal"
},
{
"scope": [
"carriage-return"
],
"settings": {
"fontStyle": "italic underline",
"foreground": "#d73a49"
},
"name": "Carriage Return"
},
{
"scope": [
"invalid.unimplemented"
],
"settings": {
"fontStyle": "bold italic underline",
"foreground": "#b31d28"
},
"name": "Invalid - Unimplemented"
},
{
"scope": [
"message.error"
],
"settings": {
"foreground": "#b31d28"
}
},
{
"scope": [
"string source"
],
"settings": {
"foreground": "#000000"
},
"name": "String embedded-source"
},
{
"scope": [
"string variable"
],
"settings": {
"foreground": "#005cc5"
},
"name": "String variable"
},
{
"scope": [
"source.regexp",
"string.regexp"
],
"settings": {
"foreground": "#032f62"
},
"name": "String.regexp"
},
{
"scope": [
"string.regexp.character-class",
"string.regexp constant.character.escape",
"string.regexp source.ruby.embedded",
"string.regexp string.regexp.arbitrary-repitition"
],
"settings": {
"foreground": "#032f62"
},
"name": "String.regexp.special"
},
{
"scope": [
"string.regexp constant.character.escape"
],
"settings": {
"fontStyle": "bold",
"foreground": "#22863a"
},
"name": "String.regexp constant.character.escape"
},
{
"scope": [
"support.constant"
],
"settings": {
"foreground": "#005cc5"
},
"name": "Support.constant"
},
{
"scope": [
"support.variable"
],
"settings": {
"foreground": "#005cc5"
},
"name": "Support.variable"
},
{
"scope": [
"meta.module-reference"
],
"settings": {
"foreground": "#005cc5"
},
"name": "meta module-reference"
},
{
"scope": [
"markup.list"
],
"settings": {
"foreground": "#735c0f"
},
"name": "Markup.list"
},
{
"scope": [
"markup.heading",
"markup.heading entity.name"
],
"settings": {
"fontStyle": "bold",
"foreground": "#005cc5"
},
"name": "Markup.heading"
},
{
"scope": [
"markup.quote"
],
"settings": {
"foreground": "#22863a"
},
"name": "Markup.quote"
},
{
"scope": [
"markup.italic"
],
"settings": {
"fontStyle": "italic",
"foreground": "#000000"
},
"name": "Markup.italic"
},
{
"scope": [
"markup.bold"
],
"settings": {
"fontStyle": "bold",
"foreground": "#000000"
},
"name": "Markup.bold"
},
{
"scope": [
"markup.raw"
],
"settings": {
"foreground": "#005cc5"
},
"name": "Markup.raw"
},
{
"scope": [
"markup.deleted",
"meta.diff.header.from-file",
"punctuation.definition.deleted"
],
"settings": {
"foreground": "#b31d28"
},
"name": "Markup.deleted"
},
{
"scope": [
"markup.inserted",
"meta.diff.header.to-file",
"punctuation.definition.inserted"
],
"settings": {
"foreground": "#22863a"
},
"name": "Markup.inserted"
},
{
"scope": [
"markup.changed",
"punctuation.definition.changed"
],
"settings": {
"foreground": "#e36209"
}
},
{
"scope": [
"markup.ignored",
"markup.untracked"
],
"settings": {
"foreground": "#005cc5"
}
},
{
"scope": [
"meta.diff.range"
],
"settings": {
"foreground": "#6f42c1",
"fontStyle": "bold"
}
},
{
"scope": [
"meta.diff.header"
],
"settings": {
"foreground": "#005cc5"
}
},
{
"scope": [
"meta.separator"
],
"settings": {
"fontStyle": "bold",
"foreground": "#005cc5"
},
"name": "Meta.separator"
},
{
"name": "Output",
"scope": [
"meta.output"
],
"settings": {
"foreground": "#005cc5"
}
},
{
"scope": [
"brackethighlighter.tag",
"brackethighlighter.curly",
"brackethighlighter.round",
"brackethighlighter.square",
"brackethighlighter.angle",
"brackethighlighter.quote"
],
"settings": {
"foreground": "#586069"
}
},
{
"scope": [
"brackethighlighter.unmatched"
],
"settings": {
"foreground": "#b31d28"
}
},
{
"scope": [
"sublimelinter.mark.error"
],
"settings": {
"foreground": "#b31d28"
}
},
{
"scope": [
"sublimelinter.mark.warning"
],
"settings": {
"foreground": "#e36209"
}
},
{
"scope": [
"sublimelinter.gutter-mark"
],
"settings": {
"foreground": "#959da5"
}
},
{
"scope": [
"constant.other.reference.link",
"string.other.link"
],
"settings": {
"foreground": "#032f62",
"fontStyle": "underline"
}
},
{
"scope": [
"meta.function-call support.function",
"meta.function-call entity.name.function"
],
"settings": {
"foreground": "#005cc5"
}
},
{
"scope": [
"keyword.operator"
],
"settings": {
"foreground": "#000000"
}
}
]
}

485
src/content/blog/ssh.md Normal file
View file

@ -0,0 +1,485 @@
---
title: 'SSH Quick Start Guide'
description: 'The fastest way to get all the SSH essentials out of the way'
pubDate: 'December 26 2023'
heroImage: '/blog-placeholder-3.jpg'
---
# SSH
SSH is the standard way to control a computer remotely. It lets us login and use
the system, despite not being right in front of it. In fact, many people can log
into the same computer and use it at the same time, though only at most 1 user
can use it directly. It's absolutely essential to know for any software
developer and CS researcher.
It's also just really cool!
![silly akemi](/akemi_silly_transparent.png)
For this course, we will be using the university's lab machines for all
assignments and lab demos. They all run Ubuntu 20.04. It's important you compile
and test your code on these machines. We will not accept situations where the
code runs perfectly on your computer, virtual machine, or really anything else
that's not a lab computer. TAs will be able to help you a lot better if you're
using the lab machines
SSH will allow you to connect to the lab machine and transfer files between the
lab machines and your computer
### Setup
You'll need a recent-ish version of OpenSSH installed on your computer. On
linux/mac you can use `ssh -V` to check your version. If that command fails, or
your version is below 8, please install openssh for your system
Macs may want to use [brew](https://formulae.brew.sh/formula/openssh), while
linux systems should use their package manager
### University Lab Machines
To ssh into a computer, we'll need its IP address. Just like with websites, we
don't actually need to remember the number, we'll instead use the domain name.
Our 34 lab machines numbered 01-34 are all at the domain `cs.ualberta.ca`.
Here's a complete list:
```
ug01.cs.ualberta.ca
ug02.cs.ualberta.ca
ug03.cs.ualberta.ca
ug04.cs.ualberta.ca
ug05.cs.ualberta.ca
ug06.cs.ualberta.ca
ug07.cs.ualberta.ca
ug08.cs.ualberta.ca
ug09.cs.ualberta.ca
ug10.cs.ualberta.ca
ug11.cs.ualberta.ca
ug12.cs.ualberta.ca
ug13.cs.ualberta.ca
ug14.cs.ualberta.ca
ug15.cs.ualberta.ca
ug16.cs.ualberta.ca
ug17.cs.ualberta.ca
ug18.cs.ualberta.ca
ug19.cs.ualberta.ca
ug20.cs.ualberta.ca
ug21.cs.ualberta.ca
ug22.cs.ualberta.ca
ug23.cs.ualberta.ca
ug24.cs.ualberta.ca
ug25.cs.ualberta.ca
ug26.cs.ualberta.ca
ug27.cs.ualberta.ca
ug28.cs.ualberta.ca
ug29.cs.ualberta.ca
ug30.cs.ualberta.ca
ug31.cs.ualberta.ca
ug32.cs.ualberta.ca
ug33.cs.ualberta.ca
ug34.cs.ualberta.ca
```
We also have other computers, though these ones are typically set aside for
CMPUT201. Usually most people use ug01-ug04, so those computers often get
overloaded and laggy. It's in your best interest to use the mid-to-higher
numbered ones
IST usually reboots these computers about once per month early morning
on Wednesday. If you're experiencing issues around that time, it might just be
since they're updating the software, so wait an hour before trying to connect
again. As a backup, there's `ohaton.cs.ualberta.ca`, which is a much slower
computer, though very rarely has any downtime
Your files are stored on a separate network-attached storage device, so no
matter which computer you login to, all your files will be there
### Connection Demo
Let's see how Alice logs into the 33rd lab machine. Her email is
`alice@ualberta.ca` so to login to the 33rd lab machine, she'll use the address
`alice@ug33.cs.ualberta.ca`
Here's what Alice sees when she attempts to connect:
```
$ ssh alice@ug33.cs.ualberta.ca
The authenticity of host 'ug33.cs.ualberta.ca (129.128.29.63)' can't be established.
ED25519 key fingerprint is SHA256:o3LbTXb16zGX3rGy9Xl1qF9eigRMYLWlsXTG6ACt3L8.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
alice@ug33.cs.ualberta.ca's password:
```
Here's what Alice typed, assuming her password is `password123`
```
ssh alice@ug33.cs.ualberta.ca
yes
password123
```
Replace the CCID and password with your own. Make sure you type `yes` when it
asks if you want to continue connecting.
If everything goes well, you'll be connected to the lab machine. If you want to
make sure, type `hostname` and hit enter. It should print `ug33`, or a different
number if you logged into one of the other machines. Type `exit` to get back to
your own computer
# SCP
Once we can connect to the lab machine, we may want to transfer files to and
from the lab machines. SSH has a tool called `scp`, which stands for
**s**sh**c**o**p**y. The syntax is very similar the to `cp` command you should
be familiar with from the linux tutorial. As a refresher, if Alice has a file
`a.txt` and she wants to duplicate it to a file called `b.txt`, she can use
```bash
cp a.txt b.txt
```
Notice how the command is always in the order `cp <from> <to>`. `scp` is almost
identical, except it adds the ability to specify which machine we want to copy
from/to. By default, it's our own computer, so it'd be identically valid to
duplicate `a.txt` using
```bash
scp a.txt b.txt
```
This is again a shorthand for typing out a relative path to each file, so Alice
could also use
```bash
scp ./a.txt ./b.txt
```
Now let's say Alice wants to make a copy of `a.txt` called `b.txt` in the
directory `/dev/shm`. All she needs to change in the command above is the path
to `b.txt`
```bash
scp ./a.txt /dev/shm/b.txt
```
Everything Alice has done so far is possible with `cp` as well. Now what if she
instead wants to copy `a.txt` from her laptop to a file called `b.txt` in the
directory `/dev/shm` on the lab machine. She'll need to prefix the path of
`b.txt` in the command above with the login address of the machine. For example,
if Alice chooses to use `ug33`, she'll type:
```bash
scp ./a.txt alice@ug33.cs.ualberta.ca:/dev/shm/b.txt
```
Notice Alice put a colon following the login address she typed to SSH into the
machine. At this point, SSH will prompt Alice for her password. Once she types
that in, her `a.txt` will be copied over the network
Alice can also copy files from the lab computer to her own laptop. Below, she
copies the `b.txt` file from `/dev/shm` on the lab machine, to her own home
directory
```bash
scp alice@ug33.cs.ualberta.ca:/dev/shm/b.txt ~/c.txt
```
It's often useful to copy entire directories over to the lab machines instead of
just a single file. For this, Alice will add the `-r` flag, which stands for
recursive, to her command. Below she copies her entire `Lab1` directory to her
`~/Documents` directory on the lab machine. Note that the `~` expands to the
home directory's path, which is usually where you'll want to put your files
```bash
scp -r Lab1 alice@ug33.cs.ualberta.ca:~/Documents
```
Now Alice has a directory called `~/Documents/Lab1` on her lab machine.
**Use caution with scp!** Just like `cp` it will overwrite files irrecoverably
without warning. Make sure your destination is right before copying, otherwise
you will **erase files**. Making frequent git commits and pushes is the best way
to avoid having to start over on a lab or assignment
# Advanced SSH
We've already covered everything SSH can do, though it may be apparent that
having to type `alice@ug33.cs.ualberta.ca` and password every time we use `ssh`
or `scp` takes a while. We also don't have a clear way to tell Github we're
logging in over SSH
Both these problems can be solved using a combination of SSH aliases and keys.
This part is not esentail for the course, though it's important in industry and
will save you a **LOT** of time this semester
## SSH Aliases
It's quite annoying having to type in the long `alice@ug33.cs.ualberta.ca` every
time. Instead, SSH provides and aliasing system, where we can using something
else
First create the file and directory `~/.ssh/config`. On unix (linux or macos),
this looks like
```bash
mkdir ~/.ssh
touch ~/.ssh/config
```
Now use a text editor to write the following into `~/.ssh/config`. Replace
`alice` with your own CCID and feel free to use a number other than `33` for the
lab machine
```sshconfig
Host lab
Hostname ug33.cs.ualberta.ca
User alice
```
Now Alice will be able to type this alias anywhere she previously used
`alice@ug33.cs.ualberta.ca`! From the previous examples, she could now use
```bash
ssh lab
scp ./a.txt lab:/dev/shm/b.txt
scp lab:/dev/shm/b.txt ~/c.txt
scp -r Lab1 lab:~/Documents
```
## SSH keys
SSH aliases shorten what we have to type, though currently we're still typing
our password every single time. Not only is this considered incredibly insecure,
it's also such a waste of time. In real-world usage of SSH, it's usually advised
to disable passwords entirely and only rely on cryptographic SSH keys to login
IST deals with the security for us, though we can still take advantage of keys
to skip the password step entirely. And remember, this is ironically considered
**more secure** than using password-based logins!
### Making a key pair
Generating an SSH key is a bit daunting for the first time, so I'll explain
every step. All you need to do is copy/paste every line into a terminal
```bash
ssh-keygen -t ed25519 -f ~/.ssh/ualberta_cs_labs -N ''
```
You should see a long message saying something about a fingerprint and printing
an art piece at the end. If instead it says something about an error, please ask
one of the TAs for assistance
The line above created a private and public cryptographic key pair. As the name
suggests, the public key is the one you can give out and the private key is the
one you should never share with anyone. If someone else obtains your private
key, they'll be able to login everywhere that key can access (your lab machine
files and github if you finish this tutorial)
Keys are nothing more than files. In fact you can go ahead and open them in your
text editor. The keys are at
```
~/.ssh/ualberta_cs_labs
~/.ssh/ualberta_cs_labs.pub
```
Where the `.pub` is the much shorter public key and the one without `.pub` is
the private key. My public key looks like:
```
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHYJVpQTIGoNSqxK7Gp9m3O4qYLR9x7+jbkcjqTBl63W akemi@Akemis-Waybook
```
While the private key will look similar to:
```
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACB2CVaUEyBqDUqsSuxqfZtzuKmC0fce/o25HI6kwZet1gAAAKBBpTVkQaU1
ZAAAAAtzc2gtZWQyNTUxOQAAACB2CVaUEyBqDUqsSuxqfZtzuKmC0fce/o25HI6kwZet1g
AAAEDBEgSLMzFVcf490TC+Cz5cbeVzWwkhGXCX7LZAqy3G5XYJVpQTIGoNSqxK7Gp9m3O4
qYLR9x7+jbkcjqTBl63WAAAAFmVsYWluYUBFbGFpbmFzLUZlbWJvb2sBAgMEBQYH
-----END OPENSSH PRIVATE KEY-----
```
**Never show this private key to anyone!** I generated a spare one above as an
example and would never actually share my private key
### Enabling login through the key
Alice will now need to let her lab machine know this key is safe to use for
authentication. She'll use the following command:
```bash
ssh-copy-id -i ~/.ssh/ualberta_cs_labs.pub alice@ug33.cs.ualberta.ca
```
Alternatively, if she already setup the `lab` alias from before, she can use
```bash
ssh-copy-id -i ~/.ssh/ualberta_cs_labs.pub lab
```
Either way, she'll be prompted to enter her password one last time
Now, she'll once again open `~/.ssh/config` in her favorite text editor and make
it look like below. The last two lines are new:
```sshconfig
Host lab
User alice
Hostname ug33.cs.ualberta.ca
IdentityFile ~/.ssh/ualberta_cs_labs
IdentitiesOnly=yes
```
### Testing if it works
If all went well, now when you use the `lab` alias, you'll automatically be
logged in, without any password! Try the following commands:
```bash
ssh lab
touch a.txt && scp ./a.txt lab:/dev/shm/b.txt
```
If you're still being prompted for a password, retry all the steps from the
beginning then ask a TA for help if the issue persists
### Logging into Github
Github also supports SSH keys! As before, the advantage is being able to `git
push` and `git fetch` without needing to type in a password.
```bash
ssh-keygen -t ed25519 -f ~/.ssh/github_main -N ''
```
Alternatively, if you'd like some extra security, you can put a password on the
SSH key itself. This'll mean that even if your key gets stolen, it'll still take
attackers a while to crack through the password, assuming your password is
sufficiently long. The convenience-security trade off here is up to you. Simply
use the command below and type in the password you want:
```bash
ssh-keygen -t ed25519 -f ~/.ssh/github_main
```
Now login to [Github](https://github.com/login) in your browser. Go into
[Settings -> SSH and GPG keys](https://github.com/settings/keys). Click "New SSH
Key" in the top right. Give it whichever title you feel is memorable, like
"laptop github key" and set key type to be "Authentication Key"
Now we'll actually need to open up our public key file and paste it in the text
field on Github. Use a text editor to open `~/.ssh/github_main.pub`. Some
examples include:
```bash
# Manually copy with your mouse
cat ~/.ssh/github_main.pub
# The following copy directly to your clipboard! Just paste on Github
cat ~/.ssh/github_main.pub | pbcopy # On MacOS
cat ~/.ssh/github_main.pub | xclip -selection clipboard # On X11-powered Linux
cat ~/.ssh/github_main.pub | wl-copy # On Wayland-powered Linux
```
Hit "Add SSH Key". Now we'll need to add a clever alias to our SSH config which
will make `git` automatically use this key for Github. Run the following command
```bash
cat <<SSH >> ~/.ssh/config
Host github.com
Hostname github.com
IdentityFile ~/.ssh/github_main
SSH
```
Now we can test if everything works with the following command. It should greet
you with your Github username if everything worked well
```
ssh -T git@github.com
```
If the above doesn't work, try
```
ssh -i ~/.ssh/github_main -T git@github.com
```
If only the second one works, you'll want to open `~/.ssh/config` in a text
editor and make sure it looks like the example below. Otherwise you likely
didn't copy/paste the right key on Github
The final `~/.ssh/config` file should look like this:
```sshconfig
Host lab
User alice
Hostname ug33.cs.ualberta.ca
IdentityFile ~/.ssh/ualberta_cs_labs
IdentitiesOnly=yes
Host github.com
Hostname github.com
IdentityFile ~/.ssh/github_main
```
### Github Over SSH
Even when you pass the SSH tests from above, `git push` will likely still be
prompting you for a password. In all likelyhood, you're still using HTTPS
instead of SSH to connect to Github. Luckily, this part is easy to fix
First, navigate to your git directory. Now run the following command
```bash
git remote -v
```
This should print something similar to the below. Your Github username and
project name will be different of course
```
origin https://github.com/aizuko/noway.moe.git (fetch)
origin https://github.com/aizuko/noway.moe.git (push)
```
This means we're currently using the HTTP protocol to communicate with Github.
It's the same protocol we use for browsing websites. However we want to use the
SSH protocol. What we'll need to change boils down to:
1. From `https:` at the front to `ssh:`
2. Prepend `git@` in front of `github.com`
3. Append `:22` right after `github.com`
For the example above, we'd run the following to change it
```bash
git remote set-url origin ssh://git@github.com:22/aizuko/noway.moe.git
```
Now when we run `git remote -v` we should see
```
github ssh://git@github.com:22/aizuko/noway.moe.git (fetch)
github ssh://git@github.com:22/aizuko/noway.moe.git (push)
```
Try doing a `git fetch` and `git push` now. It should just automatically use the
SSH key we previously setup in the `~/.ssh/config`
You will need to do this `git remote set-url` for every old repository manually.
Next time you're using `git clone` though, clone using the SSH url directly. For
example:
```bash
git clone 'ssh://git@github.com:22/aizuko/noway.moe.git
```
This will even let you clone private repositories, since it's using your SSH key
to authenticate you, no need for passwords and usernames!

View file

@ -0,0 +1,70 @@
---
title: 'Systemd Timers'
description: "Replacing Crontabs with Systemd's timer mechanism"
pubDate: 'Dec 25 2023'
heroImage: '/blog-placeholder-2.jpg'
---
# Systemd Timers
Gen Z's crontab
Generally there are 3 pieces to a timer
- The script being run
- The systemd service defining which script to run
- The systemd timer triggering the service
## Tools
`systemd-analyze calendar` can be very handy at verifying timestamps
```bash
systemd-analyze calendar *-*-* *:10,20:10
```
To find suitable targets for things like `Wants` and `After`, see
`systemd.special(7)`. If you want to check the current status of your targets,
use:
```bash
systemctl list-units --type target --state active
systemctl status network-online.target
```
## Placing files
Scripts should be put in `/usr/local/bin` if they can be run by anyone or
`/usr/local/sbin` if they should only be run by root
Define a `xxx.service` file in `/etc/systemd/system`. Set the timer as one of
its `Wants`. `network.target` may be more appropriate in some cases.
`multi-user.target` is a good default for `WantedBy`
```ini
[Unit]
Description = Sends current ip address to uni servers
Wants = broadcast_ip.timer
Wants = network.target
After = network.target
[Service]
Type = oneshot
ExecStart = /usr/local/bin/broadcast_ip.sh
[Install]
WantedBy = multi-user.target
```
Now you'll need a timer file. It's easiest to make it have the same name as the
service file and put it in the same `/etc/systemd/system`
```ini
[Unit]
Description = Sends current ip address to uni servers
Requires = broadcast_ip.service
[Timer]
Unit = broadcast_ip.service
OnCalendar = *-*-* *:15,45:00
[Install]
WantedBy = timers.target
```

View file

@ -4,6 +4,7 @@ import BaseHead from '../components/BaseHead.astro';
import Header from '../components/Header.astro';
import Footer from '../components/Footer.astro';
import FormattedDate from '../components/FormattedDate.astro';
import { Code } from 'astro:components';
type Props = CollectionEntry<'blog'>['data'];
@ -48,6 +49,7 @@ const { title, description, pubDate, updatedDate, heroImage } = Astro.props;
.prose h1 {
font-size: 60px;
border-bottom: 2px solid #000;
margin-bottom: calc(var(--font-size) / 3);
}
.prose h2 {
font-size: 40px;
@ -59,10 +61,49 @@ const { title, description, pubDate, updatedDate, heroImage } = Astro.props;
.prose h4, .prose h5, .prose h6 {
font-size: 22px;
}
p {
.prose p {
line-height: 1.5;
font-family: var(--font-sans);
margin: 16px 0;
}
.prose ul {
padding-left: 30px;
}
.prose li {
list-style-type: disc;
}
.prose img {
display: block;
margin: 30px auto;
border-radius: 22px;
filter: drop-shadow(0 4px 6px #444);
}
.prose pre {
background-color: #f6f6f6;
border-radius: 6px;
padding: 16px;
margin: 16px 0;
font-family: var(--font-mono);
filter: drop-shadow(0 2px 6px #ddd);
}
.prose pre > code[data-line-numbers] {
counter-reset: line;
}
.prose pre > code[data-line-numbers] > .line::before {
counter-increment: line;
content: counter(line);
display: inline-block;
margin-right: 2rem
width: 1rem;
text-align: left;
color: #7ca2dfad;
}
.prose pre > code > .line::before {
content: "";
display: inline-block;
width: 1rem;
text-align: right;
}
</style>
</head>

View file

@ -8,6 +8,8 @@
:root {
--font-sans: "Noto Sans", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--font-mono: 'Noto Mono', monospace;
--font-jp: "Source Han Sans", "源ノ角ゴシック", "Hiragino Sans", "HiraKakuProN-W3", "Hiragino Kaku Gothic ProN W3", "Hiragino Kaku Gothic ProN", "ヒラギノ角ゴ ProN W3", "Noto Sans", "Noto Sans CJK JP", "メイリオ", Meiryo, "游ゴシック", YuGothic, " Pゴシック", "MS PGothic", " ゴシック", "MS Gothic", sans-serif;
--box-shadow: 0 2px 6px rgba(#000, 25%), 0 8px 24px rgba(#000, 33%), 0 16px 32px rgba(#000, 33%);
--font-size: 1em;
}