Compare commits
No commits in common. "cce5f00e186a2a424e1bc81a0cc372ed8dd849f9" and "893745913f0cb126910057e8a55b7a08f2b2b0de" have entirely different histories.
cce5f00e18
...
893745913f
|
@ -4,29 +4,8 @@ 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',
|
||||
|
@ -38,23 +17,10 @@ export default defineConfig({
|
|||
inlineStylesheets: "auto",
|
||||
},
|
||||
markdown: {
|
||||
gfm: true,
|
||||
syntaxHighlight: false,
|
||||
remarkPlugins: [
|
||||
remarkGfm,
|
||||
[remarkRehype, { clobberPrefix: "" }],
|
||||
[rehypePrettyCode, options],
|
||||
],
|
||||
//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,
|
||||
//},
|
||||
gfm: true,
|
||||
}
|
||||
});
|
||||
|
|
100
package-lock.json
generated
100
package-lock.json
generated
|
@ -13,11 +13,9 @@
|
|||
"@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": {
|
||||
|
@ -78,14 +76,6 @@
|
|||
"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",
|
||||
|
@ -1916,11 +1906,6 @@
|
|||
"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",
|
||||
|
@ -2086,14 +2071,6 @@
|
|||
"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",
|
||||
|
@ -3502,18 +3479,6 @@
|
|||
"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",
|
||||
|
@ -3921,11 +3886,6 @@
|
|||
"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",
|
||||
|
@ -5524,11 +5484,6 @@
|
|||
"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",
|
||||
|
@ -6107,25 +6062,6 @@
|
|||
"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",
|
||||
|
@ -6960,32 +6896,14 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"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,
|
||||
"version": "0.6.13",
|
||||
"resolved": "https://registry.npmjs.org/shikiji/-/shikiji-0.6.13.tgz",
|
||||
"integrity": "sha512-4T7X39csvhT0p7GDnq9vysWddf2b6BeioiN3Ymhnt3xcy9tXmDcnsEFVxX18Z4YcQgEE/w48dLJ4pPPUcG9KkA==",
|
||||
"dependencies": {
|
||||
"shikiji-core": "0.9.12"
|
||||
"hast-util-to-html": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"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",
|
||||
|
@ -7894,16 +7812,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"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",
|
||||
|
|
|
@ -17,11 +17,9 @@
|
|||
"@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": {
|
||||
|
|
|
@ -1,555 +0,0 @@
|
|||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,485 +0,0 @@
|
|||
---
|
||||
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!
|
|
@ -1,70 +0,0 @@
|
|||
---
|
||||
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
|
||||
```
|
|
@ -4,7 +4,6 @@ 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'];
|
||||
|
||||
|
@ -49,7 +48,6 @@ 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;
|
||||
|
@ -61,49 +59,10 @@ const { title, description, pubDate, updatedDate, heroImage } = Astro.props;
|
|||
.prose h4, .prose h5, .prose h6 {
|
||||
font-size: 22px;
|
||||
}
|
||||
.prose p {
|
||||
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>
|
||||
|
||||
|
|
|
@ -8,8 +8,6 @@
|
|||
|
||||
: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, "MS Pゴシック", "MS PGothic", "MS ゴシック", "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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue