@@ -1,60 +0,0 @@ | |||
const _fs = require("fs"); | |||
const _markdown = require("markdown-it"); | |||
const _markdownAnchor = require("markdown-it-anchor"); | |||
module.exports = function(eleventyConfig) { | |||
eleventyConfig.setDataDeepMerge(true); | |||
eleventyConfig.addLayoutAlias("default", "layouts/default.liquid"); | |||
eleventyConfig.addLayoutAlias("page", "layouts/page.liquid"); | |||
eleventyConfig.addPassthroughCopy("assets"); | |||
eleventyConfig.addPassthroughCopy("browserconfig.xml"); | |||
eleventyConfig.addPassthroughCopy("manifest.json"); | |||
eleventyConfig.addPassthroughCopy("favicon.ico"); | |||
const markdownItRenderer = new _markdown(); | |||
eleventyConfig.addFilter("markdownify", function(str) { | |||
return markdownItRenderer.renderInline(str); | |||
}); | |||
/*eleventyConfig.setBrowserSyncConfig({ | |||
callbacks: { | |||
ready: function(err, browserSync) { | |||
const content_404 = _fs.readFileSync('_site/404.html'); | |||
browserSync.addMiddleware("*", (req, res) => { | |||
// Provides the 404 content without redirect. | |||
res.write(content_404); | |||
res.end(); | |||
}); | |||
} | |||
} | |||
});*/ | |||
return { | |||
templateFormats: [ | |||
"md", | |||
"njk", | |||
"html", | |||
"liquid" | |||
], | |||
// If your site lives in a different subdirectory, change this. | |||
// Leading or trailing slashes are all normalized away, so don’t worry about it. | |||
// If you don’t have a subdirectory, use "" or "/" (they do the same thing) | |||
// This is only used for URLs (it does not affect your file structure) | |||
pathPrefix: "/", | |||
markdownTemplateEngine: "liquid", | |||
htmlTemplateEngine: "liquid", | |||
dataTemplateEngine: "liquid", | |||
passthroughFileCopy: true, | |||
dir: { | |||
input: ".", | |||
includes: "_includes", | |||
data: "_data", | |||
output: "_site" | |||
} | |||
}; | |||
}; |
@@ -1,3 +0,0 @@ | |||
node_modules/ | |||
_site/ | |||
README.md |
@@ -1,13 +0,0 @@ | |||
name: Test Build | |||
on: [push] | |||
jobs: | |||
build: | |||
name: "Build and Test" | |||
runs-on: ubuntu-latest | |||
steps: | |||
- name: Checkout | |||
uses: actions/checkout@master | |||
- name: Build 11ty | |||
run: make build |
@@ -1,22 +0,0 @@ | |||
name: Build and Deploy | |||
on: | |||
push: | |||
branches: | |||
- master | |||
jobs: | |||
deploy: | |||
name: "Build and Deploy" | |||
runs-on: ubuntu-latest | |||
steps: | |||
- name: Checkout | |||
uses: actions/checkout@v1 | |||
- name: Build 11ty | |||
run: make build | |||
- name: Deploy to GitHub Pages | |||
uses: JamesIves/github-pages-deploy-action@releases/v3 | |||
with: | |||
ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }} | |||
BRANCH: gh-pages | |||
FOLDER: _site |
@@ -1,7 +1,6 @@ | |||
.vscode/ | |||
node_modules/ | |||
_site/ | |||
assets/css/styles.css | |||
assets/css/styles.css.map | |||
/public/build/ | |||
/public/global.css* | |||
.vscode/ | |||
.DS_Store | |||
package-install.lock | |||
pnpm-lock.yaml |
@@ -1,6 +0,0 @@ | |||
--- | |||
layout: page | |||
title: "404" | |||
--- | |||
Oh no! |
@@ -1 +0,0 @@ | |||
horrific.dev |
@@ -17,16 +17,16 @@ package-install.lock: package.json | |||
${NPM} install | |||
touch package-install.lock | |||
assets/css/styles.css: assets/css/styles.scss | |||
public/global.css: public/global.scss | |||
${NPX} sass $^ $@.tmp | |||
${NPX} -p postcss-cli postcss $@.tmp -o $@ | |||
rm $@.tmp $@.tmp.map | |||
build: install assets/css/styles.css | |||
build: install public/global.css | |||
${NPX} @11ty/eleventy | |||
serve: install assets/css/styles.css | |||
${NPX} @11ty/eleventy --serve | |||
serve: install public/global.css | |||
${NPM} run dev | |||
clean: | |||
rm package-install.lock | |||
@@ -1,15 +1,104 @@ | |||
# [horrific.dev](https://horrific.dev/) | |||
*Looking for a shareable component template? Go here --> [sveltejs/component-template](https://github.com/sveltejs/component-template)* | |||
The website for Horrific Development. Contains a bunch of stuff. | |||
--- | |||
## Building | |||
# svelte app | |||
I use [`make`](https://gnu.org/software/make/) for local testing and | |||
development. To install the project's dependencies, run `make install`. Once | |||
that is finished, simply running `make` should build and serve a local version | |||
of the site. To clean up build files and such afterwards, run `make clean`. | |||
This is a project template for [Svelte](https://svelte.dev) apps. It lives at https://github.com/sveltejs/template. | |||
## Contributing | |||
To create a new project based on this template using [degit](https://github.com/Rich-Harris/degit): | |||
Pull requests / issue reports are welcome. We don't have any contributing guides | |||
or guidelines yet, but those should be added sometime in the future. Hopefully. | |||
```bash | |||
npx degit sveltejs/template svelte-app | |||
cd svelte-app | |||
``` | |||
*Note that you will need to have [Node.js](https://nodejs.org) installed.* | |||
## Get started | |||
Install the dependencies... | |||
```bash | |||
cd svelte-app | |||
npm install | |||
``` | |||
...then start [Rollup](https://rollupjs.org): | |||
```bash | |||
npm run dev | |||
``` | |||
Navigate to [localhost:5000](http://localhost:5000). You should see your app running. Edit a component file in `src`, save it, and reload the page to see your changes. | |||
By default, the server will only respond to requests from localhost. To allow connections from other computers, edit the `sirv` commands in package.json to include the option `--host 0.0.0.0`. | |||
## Building and running in production mode | |||
To create an optimised version of the app: | |||
```bash | |||
npm run build | |||
``` | |||
You can run the newly built app with `npm run start`. This uses [sirv](https://github.com/lukeed/sirv), which is included in your package.json's `dependencies` so that the app will work when you deploy to platforms like [Heroku](https://heroku.com). | |||
## Single-page app mode | |||
By default, sirv will only respond to requests that match files in `public`. This is to maximise compatibility with static fileservers, allowing you to deploy your app anywhere. | |||
If you're building a single-page app (SPA) with multiple routes, sirv needs to be able to respond to requests for *any* path. You can make it so by editing the `"start"` command in package.json: | |||
```js | |||
"start": "sirv public --single" | |||
``` | |||
## Using TypeScript | |||
This template comes with a script to set up a TypeScript development environment, you can run it immediately after cloning the template with: | |||
```bash | |||
node scripts/setupTypeScript.js | |||
``` | |||
Or remove the script via: | |||
```bash | |||
rm scripts/setupTypeScript.js | |||
``` | |||
## Deploying to the web | |||
### With [Vercel](https://vercel.com) | |||
Install `vercel` if you haven't already: | |||
```bash | |||
npm install -g vercel | |||
``` | |||
Then, from within your project folder: | |||
```bash | |||
cd public | |||
vercel deploy --name my-project | |||
``` | |||
### With [surge](https://surge.sh/) | |||
Install `surge` if you haven't already: | |||
```bash | |||
npm install -g surge | |||
``` | |||
Then, from within your project folder: | |||
```bash | |||
npm run build | |||
surge public my-project.surge.sh | |||
``` |
@@ -1,23 +0,0 @@ | |||
[ | |||
{ | |||
"title": "HorrificDev Planning Meeting", | |||
"location": "Pittsburgh", | |||
"address": "Redhawk Coffee\n120 Meyran Avenue\nPittsburgh, PA 15213", | |||
"date": "2020-02-07T15:00:00", | |||
"description": "A meeting to plan work on the [aight documentary](https://github.com/theonesean/aight), discuss deployment of the atrocious server, and to enjoy both caffeinated beverages and the company of good friends." | |||
}, | |||
{ | |||
"title": "Personal Website Hack Session", | |||
"location": "Pittsburgh", | |||
"address": "The Big Idea Bookstore\n4812 Liberty Ave\nPittsburgh, PA 15224", | |||
"date": "2020-02-14T15:30:00", | |||
"description": "Open to everyone! We'll be spending time relaxing and working on our personal websites. Pittsburgh doesn't appear to have a [Homebrew Website Club](https://indieweb.org/Homebrew_Website_Club) yet, but that might be something we could start if people are interested in this sort of thing." | |||
}, | |||
{ | |||
"title": "SIGBOVIK Conference", | |||
"location": "Pittsburgh", | |||
"address": "Gates Hillman Complex\n4902 Forbes Ave\nPittsburgh, PA 15213", | |||
"date": "2020-04-01T17:00:00", | |||
"description": "The [SIGBOVIK conference](http://sigbovik.org/2020/) is a forum organized by the Association for Computational Heresy, containing presentations and demos on a variety of neglected areas of research. This is _not_ organized by / affiliated with horrific.dev - but it's very cool, and we encourage anyone to follow their live stream if you are interested." | |||
} | |||
] |
@@ -1,29 +0,0 @@ | |||
{ | |||
"name": "horrific.dev", | |||
"email": "mail@horrific.dev", | |||
"description": "Breaking things since 2019.", | |||
"icon": "/assets/images/logo.png", | |||
"pages": { | |||
"nav": [{ | |||
"icon": "home", | |||
"title": "Home", | |||
"url": "/" | |||
},{ | |||
"icon": "info", | |||
"title": "About", | |||
"url": "/manifesto/" | |||
},{ | |||
"icon": "event", | |||
"title": "Events", | |||
"url": "/events/" | |||
},{ | |||
"icon": "book", | |||
"title": "Wiki", | |||
"url": "/wiki/" | |||
},{ | |||
"icon": "person", | |||
"title": "Services", | |||
"url": "/hosting/" | |||
}] | |||
} | |||
} |
@@ -1,7 +0,0 @@ | |||
<footer class="footer"> | |||
<div class="container"> | |||
<a class="footer-link" href="https://code.horrific.dev/horrific">code.horrific.dev</a> | |||
<a class="footer-link" href="https://twitter.com/HorrificDev">twitter.com/HorrificDev</a> | |||
<a class="footer-link" href="mailto:mail@horrific.dev">mail@horrific.dev</a> | |||
</div> | |||
</footer> |
@@ -1,17 +0,0 @@ | |||
<form action="https://formspree.io/xoqlapvv" method="POST"> | |||
<div class="input"> | |||
<label for="name">Name</label> | |||
<input type="text" id="name" placeholder="Enter your name" name="name" required="true" aria-required="true"> | |||
</div> | |||
<div class="input"> | |||
<label for="email">Email address</label> | |||
<input type="text" id="email" aria-describedby="emailHelp" placeholder="Enter email" name="_replyto" required="true" aria-required="true"><br> | |||
</div> | |||
<small>We'll never share your data.</small> | |||
<br> | |||
<div class="input d-block"> | |||
<label for="comments">What services are you looking for?</label> | |||
<textarea style="width: 300px;" rows="3" id="comments" name="comment"></textarea> | |||
</div><br> | |||
<input class="button" type="submit"> | |||
</form> |
@@ -1,64 +0,0 @@ | |||
<meta charset="utf-8"> | |||
{% assign separator = " | " %} | |||
{% assign head_title = meta.name %} | |||
{% if title %} | |||
{% assign head_title = title | append: separator | append: meta.name %} | |||
{% elsif renderData.title %} | |||
{% assign head_title = renderData.title | append: separator | append: meta.name %} | |||
{% endif %} | |||
{% assign head_description = meta.description %} | |||
{% if description %} | |||
{% assign head_description = description %} | |||
{% elsif renderData.description %} | |||
{% assign head_description = renderData.description %} | |||
{% endif %} | |||
<meta name="description" content="{{ head_description }}"> | |||
<meta name="author" content="{{ meta.author }}"> | |||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> | |||
<title>{{ head_title }}</title> | |||
<meta name="theme-color" content="#FFFFFF"> | |||
<meta name="mobile-web-app-capable" content="yes"> | |||
<link rel="manifest" href="/manifest.json"> | |||
<meta name="application-name" content="{{ meta.name }}"> | |||
<meta name="msapplication-TileColor" content="#FFFFFF"> | |||
<meta name="msapplication-TileImage" content="/assets/images/ms-icon-144x144.png"> | |||
<meta name="msapplication-tooltip" content="{{ meta.description }}"> | |||
<meta name="msapplication-config" content="/ieconfig.xml"> | |||
<link rel="apple-touch-icon" sizes="57x57" href="/assets/images/apple-icon-57x57.png"> | |||
<link rel="apple-touch-icon" sizes="60x60" href="/assets/images/apple-icon-60x60.png"> | |||
<link rel="apple-touch-icon" sizes="72x72" href="/assets/images/apple-icon-72x72.png"> | |||
<link rel="apple-touch-icon" sizes="76x76" href="/assets/images/apple-icon-76x76.png"> | |||
<link rel="apple-touch-icon" sizes="114x114" href="/assets/images/apple-icon-114x114.png"> | |||
<link rel="apple-touch-icon" sizes="120x120" href="/assets/images/apple-icon-120x120.png"> | |||
<link rel="apple-touch-icon" sizes="144x144" href="/assets/images/apple-icon-144x144.png"> | |||
<link rel="apple-touch-icon" sizes="152x152" href="/assets/images/apple-icon-152x152.png"> | |||
<link rel="apple-touch-icon" sizes="180x180" href="/assets/images/apple-icon-180x180.png"> | |||
<link rel="icon" type="image/png" sizes="192x192" href="/assets/images/android-icon-192x192.png"> | |||
<link rel="icon" type="image/png" sizes="32x32" href="/assets/images/favicon-32x32.png"> | |||
<link rel="icon" type="image/png" sizes="96x96" href="/assets/images/favicon-96x96.png"> | |||
<link rel="icon" type="image/png" sizes="16x16" href="/assets/images/favicon-16x16.png"> | |||
<meta name="apple-mobile-web-app-capable" content="yes"> | |||
<meta name="apple-mobile-web-app-status-bar-style" content="white"> | |||
<meta name="apple-mobile-web-app-title" content="{{ meta.name }}"> | |||
<link href="//fonts.googleapis.com/css?family=Arvo" rel="stylesheet"> | |||
<link href="/assets/css/styles.css" rel="stylesheet"> | |||
<meta name="twitter:card" content="summary"> | |||
<meta name="twitter:title" content="{{ head_title }}"> | |||
<meta name="twitter:description" content="{{ head_description }}"> | |||
<meta name="twitter:image" content="https://horrific.dev{{ meta.icon }}"> | |||
<meta name="twitter:creator" content="@HorrificDev"> | |||
<meta name="twitter:site" content="@HorrificDev"> | |||
<meta name="og:type" content="website"> | |||
<meta name="og:image" content="https://horrific.dev{{ meta.icon }}"> | |||
<meta name="og:locale" content="en_US"> | |||
<meta name="og:site_name" content="{{ meta.name }}"> |
@@ -1,20 +0,0 @@ | |||
<div class="d-flex align-items-center my-4"> | |||
<img src="/assets/images/logo.png" width="50" height="50" style="border-radius: 4px;" alt="The horrific dev logo, a pixelated burning computer."> | |||
<div style="line-height: 1; display: inline-block; margin-left: 1em;"> | |||
<span style="font-size: 1.2em;">{{ meta.name }}</span><br> | |||
<small id="nav-tagline">Breaking things since 2019.</small> | |||
<script type="text/javascript"> | |||
(function() { | |||
let taglines = [ | |||
"Software is bad.", | |||
"The computers must burn.", | |||
"Breaking things since 2019.", | |||
"Have fun and break things.", | |||
"Start with the meme.", | |||
"Everyone is bad at this. It's okay." | |||
]; | |||
document.getElementById("nav-tagline").innerText = taglines[Math.floor(Math.random() * taglines.length)]; | |||
})(); | |||
</script> | |||
</div> | |||
</div> |
@@ -1,15 +0,0 @@ | |||
<!DOCTYPE html> | |||
<html lang="en"> | |||
<head> | |||
{% include head.liquid %} | |||
</head> | |||
<body class="nav-container footer-container preload"> | |||
{{ content | safe }} | |||
<script type="text/javascript" src="/assets/js/libs/jquery-3.4.1.min.js"></script> | |||
<script type="text/javascript"> | |||
$('body').removeClass("preload"); | |||
</script> | |||
</body> | |||
</html> |
@@ -1,13 +0,0 @@ | |||
--- | |||
layout: default | |||
--- | |||
{% include nav.liquid %} | |||
<main class="container"> | |||
{% include header.liquid %} | |||
{{ content | safe }} | |||
</main> | |||
{% include footer.liquid %} |
@@ -1,32 +0,0 @@ | |||
<!DOCTYPE html> | |||
<html lang="en"> | |||
<head> | |||
{% include head.liquid %} | |||
</head> | |||
<body class="nav-container footer-container"> | |||
<sidebar class="sidebar"> | |||
{% for entry in sidebar %} | |||
<div style="margin: 1.5em 0;"> | |||
<b>{{ entry.title }}</b> | |||
<ul style="margin: 0;"> | |||
{% for p in entry.pages %} | |||
<li><a href="/wiki/{{ p.url }}">{{ p.title }}</a></li> | |||
{% endfor %} | |||
</ul> | |||
</div> | |||
{% endfor %} | |||
</sidebar> | |||
{% include nav.liquid %} | |||
<main class="container"> | |||
{% include header.liquid %} | |||
{{ content | safe }} | |||
</main> | |||
{% include footer.liquid %} | |||
<script type="text/javascript" src="/assets/js/libs/jquery-3.4.1.min.js"></script> | |||
</body> | |||
</html> |
@@ -1,10 +0,0 @@ | |||
<nav class="nav"> | |||
{% assign url_split = page.url | split: "/" %} | |||
{% assign url_current = '/' | append: url_split[1] | append: '/' %} | |||
{% for item in meta.pages.nav %} | |||
<a class="nav-item{% if page.url == item.url or url_current == item.url %} active{% endif %}" href="{{ item.url }}"> | |||
<span class="nav-item-img material-icons">{{ item.icon }}</span> | |||
<span class="nav-item-title">{{ item.title }}</span> | |||
</a> | |||
{% endfor %} | |||
</nav> |
@@ -1,21 +0,0 @@ | |||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="165" height="20"> | |||
<linearGradient id="s" x2="0" y2="100%"> | |||
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/> | |||
<stop offset="1" stop-opacity=".1"/> | |||
</linearGradient> | |||
<clipPath id="r"> | |||
<rect width="165" height="20" rx="3" fill="#fff"/> | |||
</clipPath> | |||
<g clip-path="url(#r)"> | |||
<rect width="92" height="20" fill="#BBB"/> | |||
<rect x="92" width="73" height="20" fill="#e05d44"/> | |||
<rect width="165" height="20" fill="url(#s)"/> | |||
</g> | |||
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"> | |||
<image x="5" y="3" width="14" height="14" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAADsQAAA7EB9YPtSQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAGISURBVDiNpZExS8NAFMf/raFLMojN0JBkaSzVQWwGlwjZSqEgdPEzCEIH55v7GVyUTFL8AE4umoIOGiqUQop1qnIIqUP1hgw1DnolSSMOPjju8Xj3+//fO+CfsZJVJISolUqlbJpmqd/vvx5v6FHtoH3S6/Xe/wQQQtTxeGzu3l+7j2uli1arxW4jYTCfz2fNZlNIQ/Lpx5RSOQxDmdeGw2G94XsOY0zPcptPFxhjesP3HEsVEYahHM8ppTIhRM0EZKnzxzxnjOlpiPCbuqFJAABDk/D0/AEAiMGDhIMs9UJZwKa9ikJZgKFJsFQRDd9zACDuIuGAq+9PPoGzt6WFHeWXXQjpJkOTgMkM56MuivjuLUKOzKqZs1QR8D3natvaS4zQ6XRe4tYBYIogfnILeCoWv6AoSgAAp90FC9OfXfGbw0VRnPCexAh3Vr22c3P5AACH1faSGodzsYQDPgafz7btyLbtCAC2+tWESLw/4UBRlIBSCgBwXTfH6wNzBA5fV5QgvrN/xxeDvb+rPQjZkwAAAABJRU5ErkJggg=="/> | |||
<text x="555" y="150" fill="#FFFFFF" fill-opacity=".3" transform="scale(.1)" textLength="650">Powered By</text> | |||
<text x="555" y="140" fill="#010101" transform="scale(.1)" textLength="650">Powered By</text> | |||
<text x="1275" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="630">horrific.dev</text> | |||
<text x="1275" y="140" transform="scale(.1)" textLength="630">horrific.dev</text> | |||
</g> | |||
</svg> |
@@ -1,11 +0,0 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<browserconfig> | |||
<msapplication> | |||
<tile> | |||
<square70x70logo src="/assets/images/ms-icon-70x70.png"/> | |||
<square150x150logo src="/assets/images/ms-icon-150x150.png"/> | |||
<square310x310logo src="/assets/images/ms-icon-310x310.png"/> | |||
<TileColor>#ffffff</TileColor> | |||
</tile> | |||
</msapplication> | |||
</browserconfig> |
@@ -1,22 +0,0 @@ | |||
--- | |||
layout: page | |||
pagination: | |||
data: events | |||
size: 1 | |||
alias: event | |||
permalink: "/events/{{ event.date | date: '%m-%d-%Y' }}/{{ event.title | slug }}/index.html" | |||
renderData: | |||
title: "{{ event.title }}" | |||
description: "{{ event.description | markdownify | strip_html | truncate: 100 }}" | |||
--- | |||
<h1>{{ event.title }}</h1> | |||
<p> | |||
<time datetime="{{ event.date }}">{{ event.date | date: "%A, %B %d, %Y<br>@ %I:%M %P" }}</time> | |||
</p> | |||
<p style="font-size: 0.9em; opacity: 0.8;">{{ event.address | newline_to_br }}</p> | |||
<p>{{ event.description | markdownify }}</p> | |||
<p> | |||
<a href="https://maps.google.com/?q={{ event.address | newline_to_br | replace: '<br />', ' ' }}">Directions (maps.google)</a> | |||
</p> |
@@ -1,67 +0,0 @@ | |||
--- | |||
layout: page | |||
title: Community Events | |||
--- | |||
{% capture page_desc %} | |||
We organize events and meetings from time to time for various reasons - often | |||
just to chill out and enjoy good company. Most meetings are open to the public; | |||
however, we ask that you RSVP if you plan on attending, as this will help us | |||
keep track of the available space and switch locations if necessary. | |||
There is an informal mailing list to keep everyone up to date - to sign up, | |||
just... yeet an email to [mail@horrific.dev](mailto:mail@horrific.dev), I | |||
guess? We'll work on improving that process at a later date. | |||
{% endcapture %} | |||
<p>{{ page_desc | markdownify | newline_to_br | replace: '<br /><br />', '<brrr />' | replace: '<br />', ' ' | replace: '<brrr />', '</p><p>' }}</p> | |||
{% assign events_sorted = events | sort: date %} | |||
<hr> | |||
<h1>Upcoming Events...</h1> | |||
{% assign noevents = true %} | |||
{% for event in events_sorted %} | |||
{% capture time_now %}{{ 'now' | date: '%s' }}{% endcapture %} | |||
{% capture time_event %}{{ event.date | date: '%s' }}{% endcapture %} | |||
{% if time_now <= time_event %} | |||
{% assign noevents = false %} | |||
<div class="card mb-3"> | |||
<a class="card-title" href="/events/{{ event.date | date: "%m-%d-%Y" }}/{{ event.title | slug }}/">{{ event.title }}</a> | |||
<div class="card-body"> | |||
<p> | |||
<time datetime="{{ event.date }}">{{ event.date | date: "%A, %B %d, %Y @ %I:%M %P" }}</time> | |||
<br> | |||
<small class="text-tertiary-3">{{ event.address | newline_to_br | replace: '<br />', ', ' }}</small> | |||
</p> | |||
{{ event.description | markdownify }} | |||
</div> | |||
</div> | |||
{% endif %} | |||
{% endfor %} | |||
{% if noevents %} | |||
<p> | |||
There are no planned events at this time. Check back later! | |||
<br><br> | |||
</p> | |||
{% endif %} | |||
<h1>Past Events...</h1> | |||
{% assign events_sorted_reverse = events_sorted | reverse %} | |||
{% for event in events_sorted_reverse %} | |||
{% capture time_now %}{{ 'now' | date: '%s' }}{% endcapture %} | |||
{% capture time_event %}{{ event.date | date: '%s' }}{% endcapture %} | |||
{% if time_now > time_event %} | |||
<div class="card mb-3"> | |||
<a class="card-title" href="/events/{{ event.date | date: "%m-%d-%Y" }}/{{ event.title | slug }}/">{{ event.title }}</a> | |||
<div class="card-body"> | |||
<p> | |||
<time datetime="{{ event.date }}">{{ event.date | date: "%A, %B %d, %Y @ %I:%M %P" }}</time> | |||
<br> | |||
<small class="text-tertiary-3">{{ event.address | newline_to_br | replace: '<br />', ', ' }}</small> | |||
</p> | |||
{{ event.description | markdownify }} | |||
</div> | |||
</div> | |||
{% endif %} | |||
{% endfor %} |
@@ -1,22 +0,0 @@ | |||
--- | |||
layout: page | |||
title: Hosting | |||
--- | |||
Part of Horrific.Dev will include an indieweb hosting service, using ethical and | |||
open-source software, offered close-to-cost for those who want it. Currently, | |||
we're testing our equipment, software, and workflow, targeting a public launch | |||
in the summer of 2020. | |||
## Private Beta | |||
Over the next few months, we'll be testing a variety of hosting offerings | |||
for friends and trusted early adopters. If you're interested in extremely-low-cost | |||
web hosting or other services, sign up below and we'll reach out. | |||
Early adopters will have a chance to help us stress-test our services and | |||
are vital to the growth of our indieweb offerings. | |||
## Sign Up | |||
{% include form-beta.liquid %} |
@@ -1,38 +0,0 @@ | |||
--- | |||
layout: page | |||
--- | |||
**horrific.dev** is a collective organization of individual developers and | |||
enthusiasts with a focus on independent services, software, and technology. We | |||
advocate for open code, ethical computing, and tools that you control. | |||
Movements that we generally support include: | |||
- [Free Software](https://www.fsf.org/) | |||
- [Right to Repair](https://repair.org/) | |||
- [IndieWeb](https://indieweb.org/) | |||
- [Responsible Data](https://responsibledata.io/) | |||
- [The A11Y Project](https://a11yproject.com/) | |||
- [Reproducible Builds](https://reproducible-builds.org/) | |||
For a more detailed explanation of our values, see the | |||
[horrific.dev manifesto](./manifesto/). | |||
## Current Goals | |||
We are working on getting a [hosting service](/wiki/Timeframe) | |||
running, as well as writing [some scripts and automation](https://code.horrific.dev/horrific/hosting) | |||
to manage it. Once this is complete, we will be able to offer small-scale | |||
hosting services and potentially expand our website a little. | |||
The organization needs some general maintenance. We plan to set up a page on | |||
[Open Collective](https://opencollective.com/) to manage and track funding. We | |||
need to connect social media accounts to a central "mailing list" (which is | |||
waiting on the server before it can be set up). We also need to put some work | |||
into more clearly defining our values as a group. | |||
Depending on our members having free time, we have [semi-regular meetings](./events/) in Pittsburgh, PA where we drink tea and discuss software projects and current events. | |||
## Get Involved | |||
There's no membership process for our group; if you're interested, get involved. Most of our communications are through [a Discord server](https://discord.gg/Pr8eZdR) | |||
at the moment, though there are plans to potentially change this in the future. If you're interested in inexpensive, customizable hosting and other web services, [sign up](./beta/) for our private beta. |
@@ -1,41 +0,0 @@ | |||
{ | |||
"name": "horrific.dev", | |||
"icons": [ | |||
{ | |||
"src": "\/assets\/images\/android-icon-36x36.png", | |||
"sizes": "36x36", | |||
"type": "image\/png", | |||
"density": "0.75" | |||
}, | |||
{ | |||
"src": "\/assets\/images\/android-icon-48x48.png", | |||
"sizes": "48x48", | |||
"type": "image\/png", | |||
"density": "1.0" | |||
}, | |||
{ | |||
"src": "\/assets\/images\/android-icon-72x72.png", | |||
"sizes": "72x72", | |||
"type": "image\/png", | |||
"density": "1.5" | |||
}, | |||
{ | |||
"src": "\/assets\/images\/android-icon-96x96.png", | |||
"sizes": "96x96", | |||
"type": "image\/png", | |||
"density": "2.0" | |||
}, | |||
{ | |||
"src": "\/assets\/images\/android-icon-144x144.png", | |||
"sizes": "144x144", | |||
"type": "image\/png", | |||
"density": "3.0" | |||
}, | |||
{ | |||
"src": "\/assets\/images\/android-icon-192x192.png", | |||
"sizes": "192x192", | |||
"type": "image\/png", | |||
"density": "4.0" | |||
} | |||
] | |||
} |
@@ -1,66 +0,0 @@ | |||
--- | |||
layout: page | |||
title: Manifesto | |||
--- | |||
## The computers must burn | |||
Experience breeds in failure, not success. Being a "good" programmer means | |||
nothing; one that can fail will learn the most. Embrace it. Write things that | |||
break. Hack a program together without thinking of the consequences, and laugh | |||
maniacally while you watch it burn. | |||
However, it is important to make a distinction between code "failing" and code | |||
"being bad"; those ideas are not necessarily synonymous. The stereotype of a | |||
"perfect developer" that never makes mistakes is particularly harmful in this | |||
regard because it furthers the idea that a bug in your software is a reflection | |||
of you as a person. | |||
> A [1x Engineer](https://1x.engineer/)... | |||
> - Writes code that - _gasp_ - has bugs. | |||
> - Makes mistakes from time to time, and finds growth in those mistakes. | |||
> - Can feel like an imposter at times, and understands that others may, too. | |||
The point of saying this is to suggest the idea that Other Developers Make | |||
Mistakes Too, and that this might not be such a bad thing. Promoting resources | |||
for [self care in tech](https://selfcare.tech/) and being vocal about these | |||
issues is a step towards reducing the impact that impostor syndrome has on our | |||
community, and preventing anxiety that leads to eventual burnout. | |||
## Software is bad | |||
Computers suck. Nothing is perfect. In a lot of computer science, nothing _can_ | |||
be perfect. Improvement is an ongoing goal, but it can never be reached. As | |||
such, it seems wrong that it's often placed as a target. Perfection doesn't | |||
exist, and it's not for us. | |||
However, building something imperfectly doesn't mean that it's bad. The way that | |||
most software is perceived is subjective - there is no universal solution to any | |||
problem, but that's a good thing. Our individuality, the difference in our goals | |||
in life and view of the world, is part of what makes us human. No piece of | |||
software can satisfy every possible use in this regard. It can be designed to | |||
meet as many as possible, which some companies have put a vast amount of effort | |||
into doing, but it will never be perfect. | |||
Aiming for perfection caters to the majority. It implies a disregard of issues | |||
in a minor context, and makes decisions to suit a larger scope. To some extent, | |||
this has to exist everywhere, as we've already established that nothing can be | |||
perfect. In implementation, though, it means that a lot of software is built and | |||
designed for "most people". It's built with most people in mind, so that the | |||
product is used by the most customers and gains the most profit. It's built for | |||
everyone, and the outcome is perfect for no one. | |||
## Have fun and break things | |||
A lot of the people here are not programmers because they want to make money - | |||
we are programmers because we enjoy what we do. This is a bit of a dangerous | |||
idea; I am in no way suggesting that we shouldn't be paid for our work, but it | |||
would be foolish to assume that money is the only factor that influences it. | |||
Simply put, there is more to work than making money, and there is more to | |||
programming than getting paid. | |||
Enjoying our work means that we are able to freely dictate how we write our | |||
code. We aren't held back by stressful deadlines or management issues, and we | |||
are free to explore and build our software in the way that we think is right. We | |||
have the privilege to be motivated by enjoyment over monetary value, and that is | |||
something that we want to share. Software as a hobby instead of a job. |
@@ -1,34 +1,35 @@ | |||
{ | |||
"name": "horrific.dev", | |||
"name": "svelte-app", | |||
"version": "1.0.0", | |||
"description": "The website for Horrific Development.", | |||
"main": "index.js", | |||
"scripts": { | |||
"test": "echo \"Error: no test specified\" && exit 1" | |||
"build": "rollup -c", | |||
"dev": "rollup -c -w", | |||
"start": "sirv public --single", | |||
"validate": "svelte-check" | |||
}, | |||
"repository": { | |||
"type": "git", | |||
"url": "git+https://code.horrific.dev/horrific/horrific.dev.git" | |||
}, | |||
"keywords": [], | |||
"author": "James Fenn <me@jfenn.me> (https://jfenn.me/)", | |||
"license": "UNLICENSED", | |||
"bugs": { | |||
"url": "https://code.horrific.dev/horrific/horrific.dev/issues" | |||
}, | |||
"homepage": "https://horrific.dev/", | |||
"devDependencies": { | |||
"@11ty/eleventy": "^0.9.0", | |||
"@11ty/eleventy-plugin-rss": "^1.0.7", | |||
"@11ty/eleventy-plugin-syntaxhighlight": "^2.0.3", | |||
"@doubledotlabs/dot.css": "0.1.2", | |||
"autoprefixer": "^9.8.5", | |||
"bootstrap": "^4.5.0", | |||
"@doubledotlabs/dot.css": "^0.1.3", | |||
"@rollup/plugin-commonjs": "^12.0.0", | |||
"@rollup/plugin-node-resolve": "^8.0.0", | |||
"@rollup/plugin-typescript": "^4.0.0", | |||
"@tsconfig/svelte": "^1.0.0", | |||
"autoprefixer": "^9.8.6", | |||
"cssnano": "^4.1.10", | |||
"fs": "0.0.1-security", | |||
"markdown-it": "^10.0.0", | |||
"markdown-it-anchor": "^5.2.5", | |||
"mdsvex": "^0.8.3", | |||
"postcss-cli": "^7.1.1", | |||
"sass": "^1.23.2" | |||
"rollup": "^2.3.4", | |||
"rollup-plugin-livereload": "^1.0.0", | |||
"rollup-plugin-svelte": "^5.0.3", | |||
"rollup-plugin-terser": "^5.1.2", | |||
"sass": "^1.26.10", | |||
"svelte": "^3.0.0", | |||
"svelte-check": "^1.0.0", | |||
"svelte-preprocess": "^4.0.0", | |||
"svelte-routing": "^1.4.2", | |||
"tslib": "^2.0.0", | |||
"typescript": "^3.9.3" | |||
}, | |||
"dependencies": { | |||
"sirv-cli": "^1.0.0" | |||
} | |||
} |
@@ -50,7 +50,7 @@ $theme-dark: ( | |||
); | |||
@import "../../node_modules/@doubledotlabs/dot.css/scss/styles.scss"; | |||
@import "../node_modules/@doubledotlabs/dot.css/scss/styles.scss"; | |||
h1, h2, h3, h4, h5 { | |||
@include var(background-color, "primary"); | |||
@@ -69,3 +69,11 @@ h1, h2, h3, h4, h5 { | |||
p { | |||
line-height: 1.5; | |||
} | |||
b, strong { | |||
@include var(color, "tertiary-1"); | |||
} | |||
* { | |||
animation: none; | |||
} |
@@ -0,0 +1,20 @@ | |||
<!DOCTYPE html> | |||
<html lang="en"> | |||
<head> | |||
<meta charset='utf-8'> | |||
<meta name='viewport' content='width=device-width,initial-scale=1'> | |||
<title>Svelte app</title> | |||
<link rel='icon' type='image/png' href='/favicon.png'> | |||
<link href="//fonts.googleapis.com/css?family=Arvo" rel="stylesheet"> | |||
<link href="//fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> | |||
<link rel='stylesheet' href='/global.css'> | |||
<link rel='stylesheet' href='/build/bundle.css'> | |||
<script defer src='/build/bundle.js'></script> | |||
</head> | |||
<body class="nav-container footer-container"> | |||
</body> | |||
</html> |
@@ -0,0 +1,84 @@ | |||
import svelte from 'rollup-plugin-svelte'; | |||
import resolve from '@rollup/plugin-node-resolve'; | |||
import commonjs from '@rollup/plugin-commonjs'; | |||
import livereload from 'rollup-plugin-livereload'; | |||
import { terser } from 'rollup-plugin-terser'; | |||
import preprocess from 'svelte-preprocess'; | |||
import { mdsvex } from 'mdsvex'; | |||
import typescript from '@rollup/plugin-typescript'; | |||
const production = !process.env.ROLLUP_WATCH; | |||
function serve() { | |||
let server; | |||
function toExit() { | |||
if (server) server.kill(0); | |||
} | |||
return { | |||
writeBundle() { | |||
if (server) return; | |||
server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { | |||
stdio: ['ignore', 'inherit', 'inherit'], | |||
shell: true | |||
}); | |||
process.on('SIGTERM', toExit); | |||
process.on('exit', toExit); | |||
} | |||
}; | |||
} | |||
export default { | |||
input: 'src/main.ts', | |||
output: { | |||
sourcemap: true, | |||
format: 'iife', | |||
name: 'app', | |||
file: 'public/build/bundle.js' | |||
}, | |||
plugins: [ | |||
svelte({ | |||
extensions: ['.svelte', '.svx'], | |||
// enable run-time checks when not in production | |||
dev: !production, | |||
// we'll extract any component CSS out into | |||
// a separate file - better for performance | |||
css: css => { | |||
css.write('public/build/bundle.css'); | |||
}, | |||
preprocess: [ | |||
preprocess(), | |||
mdsvex() | |||
] | |||
}), | |||
// If you have external dependencies installed from | |||
// npm, you'll most likely need these plugins. In | |||
// some cases you'll need additional configuration - | |||
// consult the documentation for details: | |||
// https://github.com/rollup/plugins/tree/master/packages/commonjs | |||
resolve({ | |||
browser: true, | |||
dedupe: ['svelte'] | |||
}), | |||
commonjs(), | |||
typescript({ sourceMap: !production }), | |||
// In dev mode, call `npm run start` once | |||
// the bundle has been generated | |||
!production && serve(), | |||
// Watch the `public` directory and refresh the | |||
// browser on changes when not in production | |||
!production && livereload('public'), | |||
// If we're building for production (npm run build | |||
// instead of npm run dev), minify | |||
production && terser() | |||
], | |||
watch: { | |||
clearScreen: false | |||
} | |||
}; |
@@ -0,0 +1,31 @@ | |||
<script lang="ts"> | |||
import { Router, Route } from 'svelte-routing'; | |||
import NavLink from './components/NavLink.svelte'; | |||
import Home from './routes/Home.svx'; | |||
import About from './routes/About.svx'; | |||
import Join from './routes/Join.svx'; | |||
export let url = ""; | |||
</script> | |||
<Router url="{url}"> | |||
<nav class="nav"> | |||
<NavLink to="/" title="Home" icon="home" /> | |||
<NavLink to="/about/" title="About" icon="info" /> | |||
<NavLink to="/events/" title="Events" icon="event" /> | |||
<NavLink to="/wiki/" title="Wiki" icon="book" /> | |||
<NavLink to="/join/" title="Join" icon="person_add" /> | |||
</nav> | |||
<main class="container"> | |||
<Route path="/"><Home /></Route> | |||
<Route path="/about/"><About /></Route> | |||
<Route path="/join/"><Join /></Route> | |||
</main> | |||
<footer class="footer"> | |||
<div class="container"> | |||
<a class="footer-link" href="https://code.horrific.dev/horrific">code.horrific.dev</a> | |||
<a class="footer-link" href="https://twitter.com/HorrificDev">twitter.com/HorrificDev</a> | |||
<a class="footer-link" href="mailto:mail@horrific.dev">mail@horrific.dev</a> | |||
</div> | |||
</footer> | |||
</Router> |
@@ -0,0 +1,18 @@ | |||
<script lang="ts"> | |||
export let href = ""; | |||
export let title = ""; | |||
</script> | |||
<div class="card w-100 h-100"> | |||
{#if title} | |||
{#if href} | |||
<a class="card-title" href="{href}">{title}</a> | |||
{:else} | |||
<span class="card-title">{title}</span> | |||
{/if} | |||
{/if} | |||
<div class="card-body"> | |||
<slot/> | |||
</div> | |||
</div> |
@@ -0,0 +1,17 @@ | |||
<script lang="ts"> | |||
import { Link } from "svelte-routing"; | |||
export let to = ""; | |||
export let title = ""; | |||
export let icon = ""; | |||
function getProps({ location, href, isPartiallyCurrent, isCurrent }) { | |||
const isActive = href === "/" ? isCurrent : isPartiallyCurrent || isCurrent; | |||
return { class: "nav-item" + (isActive ? " active" : "") }; | |||
} | |||
</script> | |||
<Link to="{to}" getProps="{getProps}"> | |||
<i class="nav-item-img material-icons">{icon}</i> | |||
<span class="nav-item-title">{title}</span> | |||
</Link> |
@@ -0,0 +1,7 @@ | |||
import App from './App.svelte'; | |||
const app = new App({ | |||
target: document.body | |||
}); | |||
export default app; |
@@ -0,0 +1,19 @@ | |||
# What is horrific.dev? | |||
**horrific.dev** is a collective organization of individual developers and enthusiasts with a focus on independent services, software, and technology. We advocate for open code, ethical computing, and tools that you control. | |||
[TODO: err, expand on this a little] | |||
# What's up with the name? | |||
horrific.dev's identity is derived from a common mindset shared by many of our members: namely, the idea of software development as a perpetually imperfect pursuit - and the idea that, sometimes, failure is okay. | |||
> Experience breeds in failure, not success. Being a ["good" programmer](http://10x.engineer/) means nothing; one that can fail will learn the most. Embrace it. Write things that break. Hack a program together without thinking of the consequences, and laugh maniacally while you watch it burn. | |||
The way that most software is perceived is subjective - there is no universal solution to any problem - and that's a good thing. Our individuality, the difference in our goals in life and view of the world, is part of what makes us human. No piece of software can satisfy every possible use in this regard. It can be designed to meet as many as possible, which some companies have put a vast amount of effort into doing, but it will never be perfect. | |||
In many ways, aiming for perfection caters to the majority. It implies a disregard of issues in a minor context, and makes decisions to suit a larger scope. To some extent, this priority is inevitable, as we've already established that nothing can be perfect. In implementation, though, it means that a lot of software is built and designed for "most people". It's built with most people in mind, so that the product is used by the most customers and gains the most profit. It's built for everyone, and the outcome is perfect for no one. | |||
# What is our Code of Conduct? | |||
[TODO: code of conduct] |
@@ -0,0 +1,24 @@ | |||
**horrific.dev** is a collective organization of individual developers and enthusiasts with a focus on independent services, software, and technology. We advocate for open code, ethical computing, and tools that you control. | |||
Movements that we generally support include: | |||
- [Free Software](https://www.fsf.org/) | |||
- [Ethical Source](https://ethicalsource.dev/) | |||
- [Right to Repair](https://repair.org/) | |||
- [IndieWeb](https://indieweb.org/) | |||
- [Responsible Data](https://responsibledata.io/) | |||
- [The A11Y Project](https://a11yproject.com/) | |||
- [Reproducible Builds](https://reproducible-builds.org/) | |||
For a more detailed explanation of our values, see our [about page](/about/). | |||
## Current Goals | |||
We are working on getting a [hosting service](/wiki/Timeframe) running, as well as writing [some scripts and automation](https://code.horrific.dev/horrific/hosting) to manage it. Once this is complete, we will be able to offer small-scale hosting services and potentially expand our website a little. | |||
The organization needs some general maintenance. We now have a page on [Open Collective](https://opencollective.com/horrific-dev) to manage and track expenses. We need to connect social media accounts to a central "mailing list" (which is waiting on the server before it can be set up). We also need to put some work into more clearly defining our values as a group. | |||
Depending on our members having free time, we have [semi-regular meetings](./events/) in Pittsburgh, PA where we drink tea and discuss software projects and current events. | |||
## Get Involved | |||
Most of our communications are through [a Discord server](https://discord.jfenn.me/) at the moment, though there are plans to potentially change this in the future. If you're interested in inexpensive, customizable hosting and other web services, [sign up](/hosting/) for our private beta. |
@@ -0,0 +1,52 @@ | |||
<script lang="ts"> | |||
import Card from '../components/Card.svelte'; | |||
const memberships = [ | |||
{ | |||
title: "Participatory Membership", | |||
description: "Zero-cost access to shared services and community involvement.", | |||
items: [ | |||
"Gitea Repository Hosting", | |||
"Mastodon Account @is.a.horrific.dev", | |||
"Minecraft Server Access" | |||
] | |||
}, | |||
{ | |||
title: "Computing Membership", | |||
description: "Full access to shared services and reliable web hosting at a fixed rate.", | |||
items: [ | |||
"Web Hosting at $7/month per project", | |||
"Automated Deployment Dashboard", | |||
"LetsEncrypt SSL Certificates", | |||
"Uptime Reports & Notifications", | |||
"Weekly Offsite Backups" | |||
] | |||
}, | |||
{ | |||
title: "Core Membership", | |||
description: "Direct involvement in the organization, ability to participate and vote in meetings, with shared hosting expenses.", | |||
items: [] | |||
} | |||
]; | |||
</script> | |||
# Join Horrific.Dev | |||
Something something TODO general description of services/membership options. | |||
<div class="row"> | |||
{#each memberships as membership} | |||
<div class="col col-12 col-md-6 pb-4"> | |||
<Card title="{membership.title}"> | |||
<span>{membership.description}</span> | |||
<br><br> | |||
<strong>Includes:</strong> | |||
<ul> | |||
{#each membership.items as item} | |||
<li>{item}</li> | |||
{/each} | |||
</ul> | |||
</Card> | |||
</div> | |||
{/each} | |||
</div> |
@@ -0,0 +1,6 @@ | |||
{ | |||
"extends": "./node_modules/@tsconfig/svelte/tsconfig.json", | |||
"include": ["src/**/*"], | |||
"exclude": ["node_modules/*", "__sapper__/*", "public/*"] | |||
} |
@@ -1,82 +0,0 @@ | |||
This page contains general configuration details in all horrific machines; for machine-specific configuration, see [Hardware](/wiki/Hardware). | |||
# Server configuration: | |||
## Users | |||
Any new hosting user will have an account that can ssh onto our machines with limited access; a console/dashboard will automate most functionality - creating docker containers (which can then be ssh'd into with full access), exposing ports of a docker container, linking to domains (reverse proxy through nginx), creating/uploading SSL certs, etc. | |||
The "horrific" CLI in this repo will manage most of these features, as well as providing an admin CLI & monitoring functionality to keep track of resource usage. | |||
## Config | |||
### Nginx | |||
[Proxying containerized docker apps](https://www.thepolyglotdeveloper.com/2017/03/nginx-reverse-proxy-containerized-docker-applications/) | |||
## Security | |||
### SSH access | |||
No passwords are set; all authentication is by RSA keys only. | |||
### [fail2ban](https://www.fail2ban.org/) configuration | |||
`/etc/fail2ban/jail.local` | |||
```ini | |||
[DEFAULT] | |||
destemail = someone@horrific.dev | |||
sendername = Fail2Ban | |||
[sshd] | |||
enabled = true | |||
port = 22 | |||
[sshd-ddos] | |||
enabled = true | |||
port = 22 | |||
``` | |||
### [iptables](https://wiki.debian.org/iptables) rules | |||
[`iptables-persistent`](https://salsa.debian.org/debian/iptables-persistent/) saves/restores the iptables configuration on boot. | |||
`/etc/iptables/rules.v4` | |||
```ini | |||
*filter | |||
# Allow all loopback (lo0) traffic and drop all traffic to 127/8 that doesn't use lo0 | |||
-A INPUT -i lo -j ACCEPT | |||
-A INPUT ! -i lo -d 127.0.0.0/8 -j REJECT | |||
# Accept all established inbound connections | |||
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT | |||
# Allow all outbound traffic - you can modify this to only allow certain traffic | |||
-A OUTPUT -j ACCEPT | |||
# Allow HTTP and HTTPS connections from anywhere (the normal ports for websites and SSL). | |||
-A INPUT -p tcp --dport 80 -j ACCEPT | |||
-A INPUT -p tcp --dport 443 -j ACCEPT | |||
# Allow SSH connections | |||
# The -dport number should be the same port number you set in sshd_config | |||
-A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT | |||
# Allow ping | |||
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT | |||
# Log iptables denied calls | |||
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7 | |||
# Reject all other inbound - default deny unless explicitly allowed policy | |||
-A INPUT -j REJECT | |||
-A FORWARD -j REJECT | |||
COMMIT | |||
``` | |||
### user management | |||
https://medium.com/@mccode/processes-in-containers-should-not-run-as-root-2feae3f0df3b |
@@ -1,203 +0,0 @@ | |||
This is a simplified transcription of the user manual for the server, which can be found [here](https://galtsystems.com/sites/default/files/server-model/DL380G7%20User%20Manual.pdf), to make it somewhat easier to find things. | |||
Note: [hard drive compatibility](http://dascomputerconsultants.com/HPCompaqServerDrives.htm) | |||
# Table of Contents | |||
- [Component Identification](#component-identification) | |||
- [Front panel](#front-panel) | |||
- [Rear panel](#rear-panel) | |||
- [System board components](#system-board-components) | |||
- System maintenance switch | |||
- NMI functionality | |||
- [SAS and SATA hard drive LEDs](#sas-and-sata-hard-drive-leds) | |||
- [Hot-plug fans](#hot-plug-fans) | |||
- [Operations](#operations) | |||
- [Power up the server](#power-up-the-server) | |||
- [Power down the server](#power-down-the-server) | |||
- [Extend the server from the rack](#extend-the-server-from-the-rack) | |||
- [Remove the access panel](#remove-the-access-panel) | |||
- [Install the access panel](#install-the-access-panel) | |||
# Component Identification | |||
## Front panel | |||
- Hard drive bays (8) | |||
- SATA optical drive bay | |||
- Video connector | |||
- USB connectors (2) | |||
### LEDs & Buttons | |||
| Item | Status | | |||
|-------------------------|--------| | |||
| UID LED and button | Blue = Activated<br>Flashing blue = System being remotely managed<br>Off = Deactivated | | |||
| System health LED | Green = Normal<br>Amber = System degraded.<br>Red = System critical.<br>To identify components in degraded or critical state, see [Systems Insight Display](#systems-insight-display-led-combinations). | | |||
| Power On / Standby button & system power LED | Green = System on<br>Amber = System in standby, but power is still applied<br>Off = Power cord not attached or power supply failure. | | |||
### Systems Insight Display LED Combinations | |||
| Display LED & color | Health LED | System power LED | Status | | |||
|----------------------------|------------|------------------|--------| | |||
| Processor (amber) | Red | Amber | One or more of the following conditions may exist:<br> - Processor in socket X has failed.<br> - Processor X is not installed in the socket.<br> - Processor X is unsupported.<br> - ROM detects a failed processor during POST. | | |||
| Processor (amber) | Amber | Green | Processor in socket X is in a pre-failure condition. | | |||
| DIMM (amber) | Red | Green | One or more DIMMs have failed. | | |||
| DIMM (amber) | Amber | Green | DIMM in slot X is in a pre-failure condition. | | |||
| Overtemperature (amber) | Amber | Green | The Health Driver has detected a cautionary temperature level. | | |||
| Overtemperature (amber) | Red | Amber | The server has detected a hardware critical temperature level. | | |||
| Fan (amber) | Amber | Green | One fan has failed or has been removed. | | |||
| Fan (amber) | Red | Green | Two or more fans have failed or been removed. | | |||
| Power supply (amber) | Red | Amber | - Only one power supply is installed and that power supply is in standby.<br> - Power supply fault<br> - System board fault | | |||
| Power supply (amber) | Amber | Green | - Redundant power supply is installed and only one power supply is functional.<br> - AC power cord is not plugged into redundant power supply.<br> - Redundant power supply fault<br> - Power supply mismatch at POST or power supply mismatch through hot-plug addition. | | |||
| Power cap (off) | - | Amber | Standby | | |||
| Power cap (green) | - | Flashing green | Waiting for power | | |||
| Power cap (flashing amber) | - | Amber | Power cap has been exceeded | | |||
| Power cap (green) | - | Green | Power is available | | |||
## Rear panel | |||
- PCI slots (1-6) | |||
- Power supply bays (1,2) | |||
- USB connectors (2) | |||
- Video connector | |||
- NIC connectors (1,2,3,4) | |||
- Mouse connector (PS/2) | |||
- Keyboard connector (PS/2) | |||
- Serial connector | |||
- iLO 3 connector | |||
### LEDs & Buttons | |||
| Item | Status | | |||
|------------------------|--------| | |||
| Power supply LED | Green = Normal<br>Off = System is off or power supply has failed | | |||
| UID LED/button | Blue = Activated<br>Flashing blue = System is being managed remotely<br>Off = Deactivated | | |||
| NIC/iLO 3 activity LED | Green = Network activity<br>Flashing green = Network activity<br>Off = No network activity | | |||
| NIC/iLO 3 link LED | Green = Network link<br>Off = No network link | | |||
## System board components | |||
- SAS power connectors (A,B) | |||
- SAS connectors (A,B) | |||
- Front I/O connector | |||
- SATA optical drive connector | |||
- Internal USB connector | |||
- System battery | |||
- Power supply backplane connector | |||
- NMI jumper | |||
- System maintenance switch | |||
- Processor sockets (1,2) | |||
- Processor DIMM slots (9) {1,2} | |||
- Riser connectors (primary,secondary) | |||
- SD card slot | |||
- TPM connector | |||
- Cache module connector | |||
- Fan connectors (1-6) | |||
### System maintenance switch | |||
| Position | Default | Function | | |||
|----------|---------|----------| | |||
| S1 | Off | Off = iLO 3 security is enabled<br>On = iLO 3 security is disabled | | |||
| S2 | Off | Off = System configuration can be changed<br>On = System configuration is locked | | |||
| S3 | Off | Reserved | | |||
| S4 | Off | Reserved | | |||
| S5 | Off | Off = Power-on password is enabled<br>On = Power-on password is disabled | | |||
| S6 | Off | Off = No function<br>On = Clear NVRAM | | |||
| S7 | - | Reserved | | |||
| S8 | - | Reserved | | |||
| S9 | - | Reserved | | |||
| S10 | - | Reserved | | |||
When the system maintenance switch position 6 is set to the On position, the system is prepared to erase all system configuration settings from both CMOS and NVRAM.<br> | |||
**CAUTION:** Clearing CMOS and/or NVRAM deletes configuration information. Be sure to properly configure the server or data loss could occur. | |||
### NMI functionality | |||
An NMI crash dump enables administrators to create crash dump files when a system is hung and not responding to traditional debug mechanisms. | |||
Crash dump log analysis is an essential part of diagnosing reliability problems, such as hangs in operating systems, device drivers, and applications. Many crashes freeze a system, and the only available action for administrators is to cycle the system power. Resetting the system erases any information that could support Component identification 16 problem analysis, but the NMI feature preserves that information by performing a memory dump before a hard reset. | |||
To force the OS to invoke the NMI handler and generate a crash dump log, the administrator can do any of the following: | |||
- Short the NMI jumper pins | |||
- Press the NMI switch | |||
- Use the iLO Virtual NMI feature | |||
For additional information, see the whitepaper on the HP website: [http://h20000.www2.hp.com/bc/docs/support/SupportManual/c00797875/c00797875.pdf](http://h20000.www2.hp.com/bc/docs/support/SupportManual/c00797875/c00797875.pdf) | |||
## SAS and SATA hard drive LEDs | |||
| Item | Description | | |||
|------------------|-------------| | |||
| 1 (top right) | Fault/UID LED (amber/blue) | | |||
| 2 (bottom right) | Online LED (green) | | |||
**LED combinations** | |||
| Online/activity LED (green) | Fault/UID LED (amber/blue) | Interpretation | | |||
|-----------------------------|---------------------------------|----------------| | |||
| On, off, or flashing | Alternating amber & blue | The drive has failed, or a predictive failure alert has been received for this drive; it also has been selected by a management application. | | |||
| On, off, or flashing | Steadily blue | The drive is operating normally, and it has been selected by a management application. | | |||
| On | Off | The drive is online, but it is not active currently. | | |||
| Flashing regularly (1Hz) | Amber, flashing regularly (1Hz) | **Do not remove the drive. Removing a drive may terminate the current operation and cause data loss.** The drive is part of an array that is undergoing capacity expansion or stripe migration, but a predictive failure alert has been received for this drive. To minimize the risk of data loss, do not replace the drive until the expansion or migration is complete. | | |||
| Flashing regularly (1Hz) | Off | **Do not remove the drive. Removing a drive may terminate the current operation and cause data loss.** The drive is rebuilding, or it is part of an array that is undergoing capacity expansion or stripe migration. | | |||
| Flashing irregularly | Amber, flashing regularly (1Hz) | The drive is active, but a predictive failure alert has been received for this drive. Replace the drive as soon as possible. | | |||
| Flashing irregularly | Off | The drive is active, and it is operating normally. | | |||
| Off | Steadily amber | A critical fault condition has been identified for this drive, and the controller has placed it offline. Replace the drive as soon as possible. | | |||
| Off | Amber, flashing regularly (1Hz) | A predictive failure alert has been received for this drive. Replace the drive as soon as possible. | | |||
| Off | Off | The drive is offline, a spare, or not configured as part of an array. | | |||
## Hot-plug fans | |||
The only two valid fan configurations are listed in the following table. | |||
| Configuration | bay 1 | bay 2 | bay 3 | bay 4 | bay 5 | bay 6 | | |||
|---------------|-------|-------|-------|-------|-----------|-----------| | |||
| 1 processor | Fan | Fan | Fan | Fan | Fan blank | Fan blank | | |||
| 2 processors | Fan | Fan | Fan | Fan | Fan | Fan | | |||
For a single-processor configuration, four fans and two blanks are required in specific fan bays for redundancy. A fan failure or missing fan causes all fans to spin at high speed. A second fan failure or missing fan causes an orderly shutdown of the server. | |||
Installing more than the required number of fans in a single-processor configuration is not a supported configuration. | |||
For a dual-processor configuration, six fans are required for redundancy. A fan failure or missing fan causes all fans to spin at high speed. A second fan failure or missing fan causes an orderly shutdown of the server. | |||
The server supports variable fan speeds. The fans operate at minimum speed until a temperature change requires a fan speed increase to cool the server. The server shuts down during the following temperature-related scenarios: | |||
- At POST and in the OS, iLO 3 performs an orderly shutdown if a cautionary temperature level is detected. If the server hardware detects a critical temperature level before an orderly shutdown occurs, the server performs an immediate shutdown. | |||
- When the Thermal Shutdown feature is disabled in RBSU, iLO 3 does not perform an orderly shutdown when a cautionary temperature level is detected. Disabling this feature does not disable the server hardware from performing an immediate shutdown when a critical temperature level is detected. | |||
**CAUTION:** A thermal event can damage server components when the Thermal Shutdown feature is disabled in RBSU. | |||
# Operations | |||
## Power up the server | |||
Press the power button. | |||
## Power down the server | |||
**WARNING:** To reduce the risk of personal injury, electric shock, or damage to the equipment, remove the power cord to remove power from the server. The front panel Power On/Standby button does not completely shut off system power. Portions of the power supply and some internal circuitry remain active until AC power is removed. | |||
**IMPORTANT:** If installing a hot-plug device, it is not necessary to power down the server. | |||
1. Back up the server data. | |||
2. Shut down the operating system as directed by the operating system documentation.<br>**NOTE:** If the operating system automatically places the server in Standby mode, omit the next step. | |||
3. Press the Power On/Standby button to place the server in Standby mode. When the server activates Standby power mode, the system power LED changes to amber.<br>**IMPORTANT:** Pressing the UID button illuminates the blue UID LEDs on the front and rear panels. In a rack environment, this feature facilitates locating a server when moving between the front and rear of the rack. | |||
4. Disconnect the power cords. | |||
The system is now without power. | |||
## Extend the server from the rack | |||
1. Pull down the quick release levers on each side of the server. | |||
2. Extend the server from the rack.<br>**WARNING:** To reduce the risk of personal injury or equipment damage, be sure that the rack is adequately stabilized before extending a component from the rack. | |||
3. After performing the installation or maintenance procedure, slide the server back into the rack, and then press the server firmly into the rack to secure it in place.<br>**WARNING:** To reduce the risk of personal injury, be careful when pressing the server rail-release latches and sliding the server into the rack. The sliding rails could pinch your fingers. | |||
## Remove the access panel | |||
TODO | |||
## Install the access panel | |||
TODO |
@@ -1,3 +0,0 @@ | |||
| Nickname / Configuration | Machine | User Manual | | |||
|--------------------------|----------------------|-------------| | |||
| [atrocious](/wiki/atrocious) | HP ProLiant DL380 G7 | [manual](/wiki/HP-ProLiant-DL380-G7-User-Manual) | |
@@ -1,9 +0,0 @@ | |||
## Users | |||
New users can be created with the `useradd` command. As specified in `/etc/adduser.conf`, the default home directory mode should be `0700 / drwx------`. | |||
To give users access to the `horrific` tool, you must run `horrific admin createUser <username>`. This will generate an RSA key pair in the user's home directory and create a corresponding entry in `/etc/horrific/users.json`. | |||
## Status Page | |||
The status page at [atrocious.horrific.dev](https://atrocious.horrific.dev) is updated by a cron job; its script is stored at `/var/scripts/update-status.sh`. |
@@ -1,11 +0,0 @@ | |||
This is a non-exhaustive list of projects that will be installed on our servers, mostly for our own use. We should outline information like who these services are available to and how they can be moderated following future discussion. | |||
- [0x0](https://github.com/lachs0r/0x0) | |||
- [Mastodon](https://github.com/tootsuite/mastodon) | |||
- [Gitea](https://gitea.io/) + Jenkins ([useful tutorial/blog to follow](https://mike42.me/blog/2019-05-how-to-integrate-gitea-and-jenkins)) | |||
- [IRC](http://www.irc.org/) / Matrix | |||
- [F-Droid](https://f-droid.org/repomaker/) | |||
- [JupyterLab](https://jupyter.org/) | |||
- [Gopher Pages](https://sdf.org/?tutorials/gopher) | |||
- [npm](https://docs.npmjs.com/misc/registry#can-i-run-my-own-private-registry) | |||
- [entropic](https://github.com/entropic-dev/entropic) |
@@ -1,29 +0,0 @@ | |||
There are essentially three phases to setting up this server and realizing our (small but broad) vision for what we want to do, hosting-wise. | |||
**Phase 1: Setup** This will mostly entail setting up the OS, deployment/containerization, and increasing our capacity to a working level. As of right now, we have a functional server with a 120GB PCIe SSD for OS/speed-critical stuff. This, plus a few assorted drives (target expenditure <$100, target capacity >1TB), is essentially all we need to have a viable server for essentially any computing project. (*timeframe: end of March 2020*) | |||
**Phase 2: Usage** This is where we, and trusted/brave early adopters, start migrating our own computing projects permanently over to the server. It's important to not try to scale too quickly here, and to allow plenty of time to fix bugs, reconfigure stuff, and automate our workflows so we can scale without becoming full-time IT support. Personally, I think the end of this phase should be when we're comfortable using the server personally, plus one month for preparations. (*timeframe: end of May 2020*) | |||
**Phase 3: Reliability** I wanted to name this phase "reliability-at-scale," but I wanted to stick with the one-word naming convention. This is the big-time. By now, we should no longer be making major breaking changes to infrastructure and foundational software, and creating new projects should be 90% automated. I'm completely fine with having to SSH in to accomplish a queue of tasks that are easier for humans to do every few days, but I'm really not fine with manually creating/hooking things up, for instance. Security should be 100% figured out, implemented, and independently audited. (It may be worth paying for this before a serious launch.) This phase will entail submitting our offerings to lists of indieweb hosting, publicizing our web presence, and solidifying our budget and payment model. (*timeframe: 90 days of launch preparations, then ongoing from July 2020*) | |||
## Expansion | |||
After we're semi-seriously launched, we should think about how next to majorly expand our offerings. Other servers, drive bays, etc. We're not likely to start hitting the limits of our current server for at least six months (according to other indieweb\* people I've talked to), so here, in no particular order, are what I think we should plan to upgrade over time, when we have the resources: | |||
* automated offsite backups (Amazon Glacier) | |||
* static hosting at a lower cost | |||
* expanding software offerings to more plug-and-play CMS/app-type stuff (our own CPanel-lite would be great) | |||
* file hosting/CDN services | |||
* DNS and nameservers | |||
* an HP-compatible 3.5" drive enclosure to expand storage for our current server | |||
* a dedicated storage server with lots of 3.5" bays | |||
* network switches | |||
* dedicated rack-mounted power management | |||
* a GPU-centered compute-powerful machine for scientific computing | |||
* a dedicated business net connection | |||
* colocation services | |||
* offering VPSes (most likely need a dedicated machine) | |||
* long-term data storage (tape drives) | |||
* selling physical media (with OS images, standard stuff that we create, custom whatever, at whatever scale) | |||
This is obviously an incomplete *and* aspirational list. It's entirely possible that there isn't demand for these services, or they're difficult to do at our small scale, but I think as we upgrade and expand, it's helpful to have guiding principles and goals in mind. |
@@ -1,54 +0,0 @@ | |||
# Specifications | |||
**Processor:** Dual Intel Xeon X5650<br> | |||
**Memory:** 64GB<br> | |||
**Swap Space:** 120GB<br> | |||
**Storage:** 240GB SSD, 2.3TB HDD | |||
**System:** Debian 10.3 (buster) | |||
**SKU:** 583913-001<br> | |||
**SN:** LWCR10A861S14T | |||
# Storage Configuration | |||
## Disk 0: 111.8 GiB | |||
Disk model: Corsair Force MP300 | |||
Description: 120GB NVME PCIe SSD, used for swap space | |||
| Device | Boot | Start | End | Sectors | Size | Id | Type | | |||
| --- | --- | --- | --- | --- | --- | --- | --- | | |||
| /dev/nvme0n1p1 | | 2046 | 234440703 | 234438658 | 111.8G | 5 | Extended | | |||
| /dev/nvme0n1p5 | | 2048 | 234440703 | 234438656 | 111.8G | 82 | Linux swap / Solaris | | |||
## Disk 1: 223.6 GiB | |||
Disk model: LOGICAL VOLUME | |||
Description: 240GB SAS SSD in single-disk RAID 0, contains all OS partitions | |||
| Device | Boot | Start | End | Sectors | Size | Id | Type | | |||
| --- | --- | --- | --- | --- | --- | --- | --- | | |||
| /dev/sda1 | * | 2048 | 78125055 | 78123008 | 37.3G | 83 | Linux | | |||
| /dev/sda2 | | 78127102 | 371093503 | 292966402 | 139.7G | 5 | Extended | | |||
| /dev/sda5 | | 78127104 | 273436671 | 195309568 | 93.1G | 83 | Linux | | |||
| /dev/sda6 | | 273438720 | 371093503 | 97654784 | 46.6G | 83 | Linux | | |||
## Disk 2: 29.7 GiB | |||
Disk model: Flash Reader | |||
Description: 32GB SD card in motherboard slot; for file transfer and as emergency backup | |||
| Device | Boot | Start | End | Sectors | Size | Id | Type | | |||
| --- | --- | --- | --- | --- | --- | --- | --- | | |||
| /dev/sdb1 | | 8192 | 62333951 | 62325760 | 29.7G | c | W95 FAT32 (LBA) | |||
## Disk 3: 279.4 GiB | |||
Disk model: LOGICAL VOLUME | |||
Description: 300GB HP SAS HDD in single-disk RAID 0 | |||
## Disk 4: 931.5 GiB | |||
Disk model: LOGICAL VOLUME | |||
Description: 2x1TB HP SAS HDD in RAID 1 (very satisfying) |
@@ -1,6 +0,0 @@ | |||
Welcome to the horrific.dev hosting wiki! | |||
- [Timeframe](./Timeframe) contains our long-term goals and progress. | |||
- [Configuration](./Configuration) contains an overview of how are machines are configured. | |||
- [Hardware](./Hardware) contains a list of our machines and specific configuration details. | |||
- [Software](./Software) includes a list of services that the hosting will provide. |
@@ -1,52 +0,0 @@ | |||
{ | |||
"layout": "layouts/wiki.liquid", | |||
"sidebar": [ | |||
{ | |||
"title": "", | |||
"pages": [{ | |||
"title": "Home", | |||
"url": "./" | |||
}] | |||
}, | |||
{ | |||
"title": "Timeframe", | |||
"pages": [{ | |||
"title": "Planned phases", | |||
"url": "Timeframe" | |||
},{ | |||
"title": "Expansion", | |||
"url": "Timeframe#expansion" | |||
}] | |||
}, | |||
{ | |||
"title": "Configuration", | |||
"pages": [{ | |||
"title": "Server configuration", | |||
"url": "Configuration#server-configuration" | |||
},{ | |||
"title": "Maintenance", | |||
"url": "Maintenance" | |||
}] | |||
}, | |||
{ | |||
"title": "Hardware", | |||
"pages": [{ | |||
"title": "Overview", | |||
"url": "Hardware" | |||
},{ | |||
"title": "atrocious", | |||
"url": "atrocious" | |||
},{ | |||
"title": "User Manuals: HP ProLiant DL380 G7", | |||
"url": "HP-ProLiant-DL380-G7-User-Manual" | |||
}] | |||
}, | |||
{ | |||
"title": "Software", | |||
"pages": [{ | |||
"title": "Overview", | |||
"url": "Software" | |||
}] | |||
} | |||
] | |||
} |