Compare commits

..

47 commits

Author SHA1 Message Date
63b4438463 Fix keyscan
All checks were successful
/ build (push) Successful in 28s
2025-03-29 19:40:04 +01:00
7989f98776 Move website to Nix server
Some checks failed
/ build (push) Has been cancelled
2025-03-29 19:36:26 +01:00
2608fd281d fix_date
All checks were successful
/ build (push) Successful in 27s
2025-02-10 19:32:28 +01:00
19e2605b03 1
All checks were successful
/ build (push) Successful in 30s
2025-01-30 18:19:35 +01:00
d12dfc6d91 forgejo logot o footer
All checks were successful
/ build (push) Successful in 24s
2024-11-03 21:13:15 +01:00
5a74fb5ef5 Fix path to forgejo logo
All checks were successful
/ build (push) Successful in 24s
2024-11-03 21:09:46 +01:00
10a550aea2 Merge branch 'master' of code.polsevev.dev:polsevev/polsevev.dev
All checks were successful
/ build (push) Successful in 25s
2024-11-03 21:08:19 +01:00
1d51866188 Move to forgejo 2024-11-03 21:08:10 +01:00
f969c3620d Upgrade astro
All checks were successful
/ build (push) Successful in 24s
2024-10-29 22:12:23 +01:00
5057118cc3 Merge branch 'master' of code.polsevev.dev:polsevev/polsevev.dev
All checks were successful
/ build (push) Successful in 27s
2024-10-26 12:41:35 +02:00
66f85f80f2 Edit a bit of the text on homepage and about page 2024-10-26 12:40:55 +02:00
76a9cbb157 Merge pull request 'workflow_test' (#1) from workflow_test into master
All checks were successful
/ build (push) Successful in 26s
Reviewed-on: #1
2024-10-26 10:30:32 +00:00
12ae79ecd8 Set run to only run on master 2024-10-26 12:29:46 +02:00
354c45a260 I am not root LOL
All checks were successful
/ build (push) Successful in 27s
2024-10-26 12:24:47 +02:00
186ff13f6c Finito
Some checks failed
/ build (push) Has been cancelled
2024-10-26 12:23:41 +02:00
84585ca242 Forgot to actually join to tailscale network
Some checks failed
/ build (push) Has been cancelled
2024-10-26 12:22:09 +02:00
ce129548d1 LOL
Some checks failed
/ build (push) Has been cancelled
2024-10-26 12:19:25 +02:00
4f07ca6526 Fix could not resolve hostname
Some checks failed
/ build (push) Failing after 27s
2024-10-26 12:17:51 +02:00
62166113fa Add sharp
Some checks failed
/ build (push) Failing after 28s
2024-10-26 12:16:49 +02:00
82774c08f4 Run it!
Some checks failed
/ build (push) Failing after 20s
2024-10-26 12:13:45 +02:00
5c642d0626 Checkout
All checks were successful
/ build (push) Successful in 17s
2024-10-26 12:09:09 +02:00
6a8a1a5871 Wrong runs-on
Some checks failed
/ build (push) Failing after 1s
2024-10-26 12:00:50 +02:00
0e156d5f61 Initial test of actions
Some checks are pending
/ build (push) Waiting to run
2024-10-26 11:59:56 +02:00
7c973ac48a Change tracking code 2024-10-22 21:11:01 +02:00
0c245cb055 Add self-hosted analytics 2024-10-20 18:59:43 +02:00
b5aabf34a3 Fix wrong date on recent blogpost 2024-10-19 17:55:59 +02:00
d2bb4cf502 Readme update 2024-10-19 17:53:15 +02:00
9e9aacfbcf New server! + Blogpost about homelab 2024-10-19 17:47:25 +02:00
af1cd7ed91 Fix sorting 2024-09-29 19:14:02 +02:00
4566c85c44 Remove placeholders lol 2024-09-29 19:07:18 +02:00
bd785f0fc0 WROOONG branch on push 2024-09-29 17:20:26 +02:00
7d46ceeae7 Correct date 2024-09-29 17:18:16 +02:00
c6891b9e1f Wrong branch :) 2024-09-29 16:52:36 +02:00
1f342fb6fd Styling stuffs 2024-09-29 16:26:08 +02:00
6382e55f70 styling 2024-09-29 16:12:28 +02:00
41f6a74b69 lol 2024-09-29 16:09:51 +02:00
2b17edc92b Terraform writeup 2024-09-29 16:08:48 +02:00
92507301ac Add navigation to homelab 2024-08-23 20:38:34 +02:00
8b72fb085f improve mobile experience 2024-08-23 20:36:08 +02:00
4fbb7f0321 Merge branch 'master' of github.com:polsevev/polsevev.dev 2024-08-08 20:16:42 +02:00
71dd878651 Added homelab blog to rss 2024-08-08 20:16:20 +02:00
Rolf Martin Glomsrud
8e245ce07b
Create LICENSE 2024-08-06 15:14:36 +02:00
429e7ff3b0 Reworked some of the navigation styling 2024-08-04 21:29:22 +02:00
2dc58f20ce Reworked the homepage 2024-08-04 21:19:54 +02:00
90bab656bf Header on blog site and correction on blog post 2024-08-04 21:07:57 +02:00
614a021b1e Added homelab blog post 2024-08-04 21:01:37 +02:00
88d816c144 Finally got my own ci/cd woooo 2024-08-04 01:30:07 +02:00
49 changed files with 1561 additions and 1552 deletions

View file

@ -0,0 +1,14 @@
on:
push:
branches:
- master
jobs:
build:
runs-on: ubuntu
steps:
- uses: actions/checkout@v4
- run: npm i
- run: npm run build
- run: ssh-keyscan hephaestus >> ~/.ssh/known_hosts
- run: /bin/rsync -avzh ./dist ansible@hephaestus:/var/www/polsevev/

View file

@ -1,28 +0,0 @@
name: Build on self hosted runner
on:
push:
branches:
- master2
jobs:
build:
name: Build Website
runs-on: self-hosted
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- run: |
npm install
npm run build
- name: Rsync to server
uses: burnett01/rsync-deployments@5.2
with:
switches: -avzr --delete
path: dist
remote_path: /var/www/polsevev
remote_host: ${{secrets.SERVER_IP}}
remote_user: ansible
remote_key: ${{secrets.SSH_PRIVATE_KEY}}
remote_port: 22

View file

@ -1,17 +0,0 @@
when:
- event: push
branch: testing
steps:
- name: build
image: local/builder
commands:
- npm install
- npm run build
- mkdir /root/.ssh && chmod 0700 /root/.ssh
- echo $SSH_KEY | base64 --decode >> /root/.ssh/id_rsa
- chmod 0600 /root/.ssh/id_rsa
- ssh-keyscan $REMOTE_IP >> /root/.ssh/known_hosts
- /bin/rsync -avzh ./dist ansible@$REMOTE_IP:/var/www/polsevev/dist
secrets: [ SSH_KEY, remote_ip ]

24
LICENSE Normal file
View file

@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <https://unlicense.org>

View file

@ -1,5 +1,5 @@
# Test 2 # Welcome!
I am evaluating if i want to use Astro to make this website :)
This is a repo for my website [polsevev.dev](polsevev.dev)
You are welcome to look at, and use, the code. If you want submit a PR you can, but i prolly won't accept it, as this is just a place for mye to publish things on the interwebs while avoiding using social media.

View file

@ -5,6 +5,6 @@ import sitemap from '@astrojs/sitemap';
// https://astro.build/config // https://astro.build/config
export default defineConfig({ export default defineConfig({
site: 'https://example.com', site: 'https://polsevev.dev',
integrations: [mdx(), sitemap()], integrations: [mdx(), sitemap()],
}); });

View file

@ -1,68 +0,0 @@
# Astro Starter Kit: Blog
```sh
npm create astro@latest -- --template blog
```
[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/blog)
[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/blog)
[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/withastro/astro?devcontainer_path=.devcontainer/blog/devcontainer.json)
> 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun!
![blog](https://github.com/withastro/astro/assets/2244813/ff10799f-a816-4703-b967-c78997e8323d)
Features:
- ✅ Minimal styling (make it your own!)
- ✅ 100/100 Lighthouse performance
- ✅ SEO-friendly with canonical URLs and OpenGraph data
- ✅ Sitemap support
- ✅ RSS Feed support
- ✅ Markdown & MDX support
## 🚀 Project Structure
Inside of your Astro project, you'll see the following folders and files:
```text
├── public/
├── src/
│   ├── components/
│   ├── content/
│   ├── layouts/
│   └── pages/
├── astro.config.mjs
├── README.md
├── package.json
└── tsconfig.json
```
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
The `src/content/` directory contains "collections" of related Markdown and MDX documents. Use `getCollection()` to retrieve posts from `src/content/blog/`, and type-check your frontmatter using an optional schema. See [Astro's Content Collections docs](https://docs.astro.build/en/guides/content-collections/) to learn more.
Any static assets, like images, can be placed in the `public/` directory.
## 🧞 Commands
All commands are run from the root of the project, from a terminal:
| Command | Action |
| :------------------------ | :----------------------------------------------- |
| `npm install` | Installs dependencies |
| `npm run dev` | Starts local dev server at `localhost:4321` |
| `npm run build` | Build your production site to `./dist/` |
| `npm run preview` | Preview your build locally, before deploying |
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
| `npm run astro -- --help` | Get help using the Astro CLI |
## 👀 Want to learn more?
Check out [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).
## Credit
This theme is based off of the lovely [Bear Blog](https://github.com/HermanMartinus/bearblog/).

2262
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -10,11 +10,12 @@
"astro": "astro" "astro": "astro"
}, },
"dependencies": { "dependencies": {
"@astrojs/mdx": "^3.1.3", "@astrojs/check": "^0.9.4",
"@astrojs/rss": "^4.0.7", "@astrojs/mdx": "^3.1.8",
"@astrojs/sitemap": "^3.1.6", "@astrojs/rss": "^4.0.9",
"astro": "^4.13.1", "@astrojs/sitemap": "^3.2.1",
"@astrojs/check": "^0.9.1", "astro": "^4.16.7",
"sharp": "^0.33.5",
"typescript": "^5.5.4" "typescript": "^5.5.4"
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

View file

@ -1,9 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 128 128">
<path d="M50.4 78.5a75.1 75.1 0 0 0-28.5 6.9l24.2-65.7c.7-2 1.9-3.2 3.4-3.2h29c1.5 0 2.7 1.2 3.4 3.2l24.2 65.7s-11.6-7-28.5-7L67 45.5c-.4-1.7-1.6-2.8-2.9-2.8-1.3 0-2.5 1.1-2.9 2.7L50.4 78.5Zm-1.1 28.2Zm-4.2-20.2c-2 6.6-.6 15.8 4.2 20.2a17.5 17.5 0 0 1 .2-.7 5.5 5.5 0 0 1 5.7-4.5c2.8.1 4.3 1.5 4.7 4.7.2 1.1.2 2.3.2 3.5v.4c0 2.7.7 5.2 2.2 7.4a13 13 0 0 0 5.7 4.9v-.3l-.2-.3c-1.8-5.6-.5-9.5 4.4-12.8l1.5-1a73 73 0 0 0 3.2-2.2 16 16 0 0 0 6.8-11.4c.3-2 .1-4-.6-6l-.8.6-1.6 1a37 37 0 0 1-22.4 2.7c-5-.7-9.7-2-13.2-6.2Z" />
<style>
path { fill: #000; }
@media (prefers-color-scheme: dark) {
path { fill: #FFF; }
}
</style>
</svg>

Before

Width:  |  Height:  |  Size: 749 B

BIN
public/images/self.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

View file

@ -0,0 +1,40 @@
<svg viewBox="0 0 212 212" xmlns="http://www.w3.org/2000/svg">
<metadata
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
>
<rdf:RDF>
<cc:Work rdf:about="https://codeberg.org/forgejo/meta/src/branch/readme/branding#logo">
<dc:title>Forgejo logo</dc:title>
<cc:creator rdf:resource="https://caesarschinas.com/"><cc:attributionName>Caesar Schinas</cc:attributionName></cc:creator>
<cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
</cc:Work>
</rdf:RDF>
</metadata>
<style type="text/css">
circle {
fill: none;
stroke: #000;
stroke-width: 15;
}
path {
fill: none;
stroke: #000;
stroke-width: 25;
}
.orange {
stroke:#ff6600;
}
.red {
stroke:#d40000;
}
</style>
<g transform="translate(6,6)">
<path d="M58 168 v-98 a50 50 0 0 1 50-50 h20" class="orange" />
<path d="M58 168 v-30 a50 50 0 0 1 50-50 h20" class="red" />
<circle cx="142" cy="20" r="18" class="orange" />
<circle cx="142" cy="88" r="18" class="red" />
<circle cx="58" cy="180" r="18" class="red" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -11,13 +11,13 @@ interface Props {
const canonicalURL = new URL(Astro.url.pathname, Astro.site); const canonicalURL = new URL(Astro.url.pathname, Astro.site);
const { title, description, image = '/blog-placeholder-1.jpg' } = Astro.props; const { title, description, image = '/self.png' } = Astro.props;
--- ---
<!-- Global Metadata --> <!-- Global Metadata -->
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" /> <meta name="viewport" content="width=device-width,initial-scale=1" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <link rel="icon" type="image/svg+xml" href="/self.png" />
<meta name="generator" content={Astro.generator} /> <meta name="generator" content={Astro.generator} />
<!-- Font preloads --> <!-- Font preloads -->
@ -45,3 +45,5 @@ const { title, description, image = '/blog-placeholder-1.jpg' } = Astro.props;
<meta property="twitter:title" content={title} /> <meta property="twitter:title" content={title} />
<meta property="twitter:description" content={description} /> <meta property="twitter:description" content={description} />
<meta property="twitter:image" content={new URL(image, Astro.url)} /> <meta property="twitter:image" content={new URL(image, Astro.url)} />
<script defer src="https://umami.polsevev.dev/script.js" data-website-id="84ead158-3295-4160-8b05-48d56cf7337b"></script>

View file

@ -5,37 +5,33 @@ const today = new Date();
<footer> <footer>
&copy; {today.getFullYear()} Rolf Martin Glomsrud. All rights reserved. &copy; {today.getFullYear()} Rolf Martin Glomsrud. All rights reserved.
<div class="social-links"> <div class="social-links">
<a href="https://github.com/polsevev" target="_blank"> <a href="https://code.polsevev.dev" target="_blank" >
<span class="sr-only">My Github?</span> <span class="sr-only">My Github?</span>
<svg viewBox="0 0 16 16" aria-hidden="true" width="32" height="32" astro-icon="social/github" <img src="/svg/Forgejo_logo.svg"/>
><path <svg viewBox="0 0 16 16" aria-hidden="true" width="32" height="32" astro-icon="social/github" ></svg>
fill="white" </a>
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z"
></path></svg
>
</a> </a>
</div> </div>
</footer> </footer>
<style> <style>
footer { footer {
padding: 2em 1em 6em 1em; padding: 1em 1em 1em 1em;
/* background: linear-gradient(var(--gray-gradient)) no-repeat;'*/
color: white; color: white;
background-color: rgb(198, 60, 81); background-color: rgb(198, 60, 81);
text-align: center; text-align: center;
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
margin-top: 0.5rem; margin-top: 2rem;
margin-bottom: 0.5rem; margin-bottom: 2rem;
border-radius: 10px; border-radius: 10px;
width: 100%; width: 90%;
height: 0em;
max-width: 1000px;
} }
.social-links { .social-links {
display: flex; display: flex;
justify-content: center; justify-content: center;
gap: 1em;
} }
.social-links a { .social-links a {
text-decoration: none; text-decoration: none;
@ -44,4 +40,8 @@ const today = new Date();
.social-links a:hover { .social-links a:hover {
color: rgb(var(--gray-dark)); color: rgb(var(--gray-dark));
} }
img{
background-color: white;
padding: 5px;
}
</style> </style>

View file

@ -7,34 +7,32 @@ import { SITE_TITLE } from '../consts';
<nav> <nav>
<h2><a href="/">{SITE_TITLE}</a></h2> <h2><a href="/">{SITE_TITLE}</a></h2>
<div class="internal-links"> <div class="internal-links">
<HeaderLink href="/">Home</HeaderLink> <HeaderLink href="/">~/</HeaderLink>
<HeaderLink href="/blog">Blog</HeaderLink> <HeaderLink href="/blog">~/blog</HeaderLink>
<HeaderLink href="/about">About</HeaderLink> <HeaderLink href="/about">~/about</HeaderLink>
<HeaderLink href="/homelab">Homelab</HeaderLink>
</div> </div>
<div class="social-links"> <div class="social-links">
<a href="https://github.com/polsevev" target="_blank"> <a href="https://code.polsevev.dev" target="_blank" >
<span class="sr-only">My Github?</span> <span class="sr-only">My Github?</span>
<svg viewBox="0 0 16 16" aria-hidden="true" width="32" height="32" astro-icon="social/github" <img src="/svg/Forgejo_logo.svg"/>
><path <svg viewBox="0 0 16 16" aria-hidden="true" width="32" height="32" astro-icon="social/github" ></svg>
fill="currentColor"
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z"
></path></svg
>
</a> </a>
</div> </div>
</nav> </nav>
</header> </header>
<style> <style>
header { header {
margin: 0; padding: 0.5em 0.5em 0.5em 0.5em;
padding: 0 1em; background-color: rgb(198, 60, 81);
background-color: rgb(198, 60, 81); box-shadow: 0 2px 8px rgba(var(--black), 5%);
box-shadow: 0 2px 8px rgba(var(--black), 5%);
border-radius: 10px; border-radius: 10px;
margin-top: 0.5rem; margin-left: auto;
margin-right: auto;
margin-top: 2rem;
margin-bottom: 2rem;
color: white; color: white;
width: 100%; width: 90%;
max-width: 1000px;
} }
h2 { h2 {
margin: 0; margin: 0;
@ -52,14 +50,18 @@ import { SITE_TITLE } from '../consts';
justify-content: space-between; justify-content: space-between;
} }
nav a { nav a {
padding: 1em 0.5em; padding: 0.5em 0.5em;
color: var(--black); color: var(--black);
border-bottom: 4px solid transparent; border-bottom: 4px solid transparent;
text-decoration: none; text-decoration: none;
} }
img{
background-color: white;
padding: 5px;
}
nav a.active { nav a.active {
text-decoration: none; text-decoration: none;
border-bottom-color: var(--accent); border-bottom-color: cyan;
} }
.social-links, .social-links,
.social-links a { .social-links a {
@ -69,5 +71,8 @@ import { SITE_TITLE } from '../consts';
.social-links { .social-links {
display: none; display: none;
} }
nav a {
padding: 0.2em 0.2em;
}
} }
</style> </style>

View file

@ -17,9 +17,10 @@ const isActive = href === pathname || href === '/' + subpath?.[0];
a { a {
display: inline-block; display: inline-block;
text-decoration: none; text-decoration: none;
} }
a.active { a.active {
font-weight: bolder; font-weight: bolder;
text-decoration: underline; text-decoreation: underline;
} }
</style> </style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

View file

@ -0,0 +1,11 @@
---
title: I got a split keyboard!
description: I am now a superior developer
pubDate: 1.30.2025
---
As can be read in the title, i finally caved and bought one. I am currently writing this post using it and it is better than i expected.
I will do a full writeup of my experience learning a split keyboard sometime in the future, just wanted to share the excitement!
![](./images/keyboard.jpg)

View file

@ -0,0 +1,28 @@
---
title: Homelab update
description: I did some major renovations to my homelab this week
pubDate: 10.19.2024
---
## My homelab used to be on the floor
Yeah, you read that right, no rack here. While i don't have any pictures, because i actually was ashamed of it, my homelab used to be on the floor under my desk. With a ratsnest of wires behind all the "servers", and the heat eminating from it mimicking the scorching Norwegian summer (so not that hot lol). On a random wednesday i decided to do something about this.
### Well, what?
As i have seen time and time again on [r/homelab](https://reddit.com/r/homelab), people use proper server racks. However, i live in a 32 m² appartment (more an overgrown hotel room), so finding a small but still usable rack turned out to be a challenge. I did some research and looked at the options availible to me. Turns out getting a proper rack would be quite expensive where i live. This is for several reasons, i don't have easy access to a large van, so it had to be shipped, meaning i can't go for something used, I don't have any proper rack mount servers and getting shelves for a rack is also not cheap. Therefore, after browsing reddit for a bit, i decided to go with a Ikea [Ekenabben](https://www.ikea.com/no/no/p/ekenabben-apen-hylle-asp-hvit-10487816/).
### The pain, but in the end, glory!
I fucking hate cable managing. There is no fun in it in my opinion, it takes ages and makes it difficult to make changes. But the end result is so satisfying. I think the picture speaks for itself, cables are routed behind the legs of the rack (where applicable) and the power adapters for the mini pcs are hidden below the bottom shelf. I love this.
![](./images/homelab_revamp.jpg)
To give a super quick rundown. At the top i have my 3d printer and free space for random things (see the raspberry pi). On the shelf below there is a wireless keyboard and mouse (for debugging broken machines), a label maker (god i love that thing), 5 mini pcs used as proxmox hosts, a 24 port unmanaged gigabit switch (behind the pcs) as well as a wifi access point. On the bottom shelf i have the two most powerful proxmox hosts, and free space for future servers (i have a problem).
If you wish to read in a bit more detail about my homelab, check out [/homelab](/homelab)
### Fin
I just wanted to share the excitement i have now, as my homelab always used to be a mess. So i hope i can finally maintain it this time (probably not xD). Thanks for reading!
![](./images/cable_management.jpg)

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View file

@ -0,0 +1,140 @@
---
title: Terraform + Proxmox = <3
description: Using Terraform to deploy Virtual Machines
pubDate: 09.29.2024
---
## I am tired of UIs
Up until now, every time i wanted to deploy a VM in my homelab i did it with the Proxmox GUI. Don't get me wrong, the GUI is nice, but i would like to not have to repeat the same mundane task every time i want a new VM.
There is an argument to be made that i probably shouldn't run that many VMs, and that for the number of VMs i need, this isn't worth it. However, being able to deploy a VM by just changing a few variables in a file and running `terraform apply` just tickles something in my nerd brain.
I also really like the repeatability of this, as i use these VM definitions to deploy K3S hosts, docker hosts and others where i want a "default" setup.
## Initial requirements
To use Terraform with Proxmox we use a privoder created by [Telmate](https://github.com/Telmate/terraform-provider-proxmox). We create the initial `provider.tf` file as so:
```json
terraform {
required_providers {
proxmox = {
source = "telmate/proxmox"
version = "3.0.1-rc3"
}
}
}
variable "proxmox_api_url" {
type = string
}
variable "proxmox_user" {
type = string
sensitive = true
}
variable "proxmox_password" {
type = string
sensitive = true
}
variable "ssh_public_key" {
type = string
}
provider "proxmox"{
pm_api_url = var.proxmox_api_url
pm_user = var.proxmox_user
pm_password = var.proxmox_password
pm_tls_insecure = true
pm_otp = ""
}
```
I have stored all secrets to access the proxmox API in custom variables located in a `.auto.tfvars` file that i do not track in git. Those variables are defined in the provider such that if they are not present Terraform will complain.
In this step i had some trouble, as you can see i use a release candidate version. There seems to be a bug in version `2.9.3`, and instead of trying to track it down i just switched to release candidate.
## Defining the virtual machine
Now as i mentioned previously, i already have templates created in my proxmox cluster (i made these with Ansible). Therefore i can use these as a base for the provisioning of a new VM.
Here is an example definition of a VM
```terraform
resource "proxmox_vm_qemu" "havneboks" {
name = "havneboks"
desc = "Docker master"
target_node = "poseidon"
agent = 1
onboot = true
clone = "VM 9001"
cores = 4
sockets = 1
cpu = "host"
memory = 3096
# Setup the disk
disks {
ide {
ide2 {
cloudinit {
storage = "basseng"
}
}
}
scsi {
scsi0 {
disk {
size = "10G"
storage = "basseng"
}
}
}
}
network {
bridge = "vmbr0"
model = "virtio"
}
scsihw = "virtio-scsi-pci"
os_type = "cloud-init"
ipconfig0 = "ip=192.168.1.51/24,gw=192.168.1.1"
nameserver = "192.168.1.69"
ciuser = "ansible"
sshkeys = var.ssh_public_key
}
```
A VM is defined using the resource type of `proxmox_vm_qemu` with a name. I really like to use the names of the service just translated to norwegian, so in this case, this VM is called `havneboks` (meaning docker box).
- name: The name of the VM (hostname)
- desc: A description of the VM
- target_node: Which node in the cluster should the VM be provisioned to, in this case i provision it to the node `poseidon`(hostname)
- agent: Just select 1
- onboot: Set the VM to start when the host boots
- clone: Which template to clone the VM from
- cores: How much horsepowa u want?
- sockets: I only got 1 cpu in each of my boxes
- memory: How much RAM u want?
Now, a really important part of this is the disk setup, as you have to mimic the setup of the template (sizes can be chosen freely). So in my case, i have the cloud-init disk on `ide2` and the OS disk on `scsi0` in the template. Therefore we create the same exact setup for this resource.
- network: Just mimic the cloud-init
- scsihw: Which hardware do you want the host system to use to provide scsi?
- os_type: I use cloud-init, so we select cloud-init
- ipconfig: Now this is quite interesting, you should set a static IP and gateway such that the VM starts with a proper IP adress (you can also use DHCP here)
- namesever: I use a custom dns on adress `.69`(nice) so i set that, but if this is not set it will use "same as host"
- ciuser: A user to be created by cloud-init for this VM
- sshkeys: Initial SSH public keys to allow access. This is stored in a variable in my case.
## Just run?
Bing bang bom. You can now deploy your VM fully automatically and about 43 seconds later access it via SSH. Now all i did was configure it with ansible, and i have a fully reproducible homelab setup.
If you want to have a look at my homelab infrastructure as code repo, you can find it at [polsevev/homelab](https://github.com/polsevev/homelab)
![](./images/i-have-homelab.webp)

View file

@ -4,4 +4,41 @@ description: Setting up my own CI with Woodpecker!
pubDate: 08.03.2024 pubDate: 08.03.2024
--- ---
I am currently working on setting opp Woodpecker as my CI. Will write a post about this here :) ## Self hosted CI/CD!
Yesterday, i decided that i was tired of using Github Actions to deploy my code from Github. So i decided to self host my own CI/CD. This is mostly because i am not comfortable having port 22 on my web server be publicly accessible on the internet.
To do this, i went down quite the rabbit hole. First i looked at [TeamCity](https://www.jetbrains.com/teamcity/) from JetBrains as this is what i use at work. It looked promising, however i decided it was too complex and had too many features i did not really care about.
Then i stumbled across [Drone](https://www.drone.io/), which seemed to fit my use-case. However it has since gotten very corporate when it was bought up, so i decided to go with the open source fork called [Woodpecker](https://woodpecker-ci.org/)
This turned out to be a bit of a bigger challenge than i first thought, but i somehow got it up and running in the end. Follow along!
### Installing
This was by far the easiest. As i have not gotten around to setting up my Kubernetes cluster yet, and i wanted to start of simple. I just used the docker compose provided by the Woodpecker team.
To provide integration with Github, i use a github Oauth2 App i made in the github UI, this is very well explained in the documentation of Woodpecker.
Now that i have configured the docker compose, i created a VM on [cronus](/homelab/servers/oceanus) and deployed the compose file using Ansible.
### Setting up a pipeline
Writing the pipeline was simple enough, as it has a very similar syntax to Github actions. However, i needed a docker image for the pipeline to run in. This actually turned out to be a challenge, as i currently do not have a docker registry in my homelab (i will be setting up Gitea in the future dw).
To solve the docker registry problem, i decided to simply build the image locally on the server. Ansible comes to the rescue again. I wrote a simple playbook that builds the docker image on the VM such that it is available to Woodpecker. Missing registry problem solved!
Now finally, i could make my own image that had all the dependencies for this website!
We were not out of the woods yet however, i still had to figure out how i wanted to transfer the files to the server they will be hosted on. Previously i had used rsync to transfer them into a directory on my web server, and i decided to do something similar this time.
However, since i did not want to put the SSH keys into the docker image.
So i ended up adding a private ssh key into the secret store of Woodpecker. This allows rsync to communicate with my web server.
This meant i have to distribute the public key to the web server beforehand, ansible saved the day again.
### Pipeline finished
Finally, i could deploy this very website, using woodpecker to my own web server, all without exposing port 22 on the web server to the internet.
![](./images/borat-borat-very-nice.gif)

View file

@ -11,7 +11,7 @@ Oceanus is my main VM server. It used to be an office PC, but has since been re-
- MODEL: HP Elitedesk 600 G3 - MODEL: HP Elitedesk 600 G3
- CPU: i7 6700 - CPU: i7 6700
- RAM: 16 GB DDR4 - RAM: 32 GB DDR4
- Storage: - Storage:
- 256 GB NVME SSD - 256 GB NVME SSD
- 128 GB SATA SSD - 128 GB SATA SSD
@ -20,15 +20,10 @@ Oceanus is my main VM server. It used to be an office PC, but has since been re-
Currently this server has quite a bit of purpose, but i will probably move most of the stateless applications from this into my K3S cluster. Currently this server has quite a bit of purpose, but i will probably move most of the stateless applications from this into my K3S cluster.
- lb-1 - Opnsense
- HAproxy load-balancer - This server currently runs my firewall, which i have behind the ISP router using DMZ to not have double NAT (even though is technically still is double NAT)
- nginx-public - Game servers
- Temporary NGINX until i get K3S up and running - I run Factorio and Feed the Beast servers on this machine
- wireguard
- Hosts a wireguard instance i use for VPN
- grafana
- ALL THE DASHBOARDS!
- woodpecker_worker
- This is a WIP of setting up my own CI
![](./images/oceanus.png)
![](./images/elitedesk_800.jpg)

View file

@ -24,4 +24,4 @@ This server is running proxmox at the moment, to allow for virtualization of all
- k3s_worker - k3s_worker
- Worker in my K3S cluster - Worker in my K3S cluster
![](./images/cluster.png) ![](./images/cluster.jpg)

View file

@ -2,9 +2,10 @@
title: 'Hades' title: 'Hades'
lastUpdated: '03.08.2024' lastUpdated: '03.08.2024'
--- ---
## What is it?
Hades is a node in my cluster of 5 mini PCs. It follows the exact same configuration as the other nodes for consistency. It used to be an office PC, but has since been re-purposed as a tiny home server. Hades is a node in my cluster of 5 mini PCs. It follows the exact same configuration as the other nodes for consistency. It used to be an office PC, but has since been re-purposed as a tiny home server.
## Specs
- MODEL: HP Elitedesk 705 G3 mini - MODEL: HP Elitedesk 705 G3 mini
- CPU: AMD A10-8770E - CPU: AMD A10-8770E
- RAM: 16 GB DDR4 - RAM: 16 GB DDR4
@ -21,4 +22,4 @@ This server is running proxmox at the moment, to allow for virtualization of all
- k3s_worker - k3s_worker
- Worker in my K3S cluster - Worker in my K3S cluster
![](./images/cluster.png) ![](./images/cluster.jpg)

View file

@ -2,9 +2,9 @@
title: 'Hermes' title: 'Hermes'
lastUpdated: '03.08.2024' lastUpdated: '03.08.2024'
--- ---
## What is it?
Hermes is a node in my cluster of 5 mini PCs. It follows the exact same configuration as the other nodes for consistency. It used to be an office PC, but has since been re-purposed as a tiny home server. Hermes is a node in my cluster of 5 mini PCs. It follows the exact same configuration as the other nodes for consistency. It used to be an office PC, but has since been re-purposed as a tiny home server.
## Specs
- MODEL: HP Elitedesk 705 G3 mini - MODEL: HP Elitedesk 705 G3 mini
- CPU: AMD A10-8770E - CPU: AMD A10-8770E
- RAM: 16 GB DDR4 - RAM: 16 GB DDR4
@ -21,4 +21,4 @@ This server is running proxmox at the moment, to allow for virtualization of all
- k3s_worker - k3s_worker
- Worker in my K3S cluster - Worker in my K3S cluster
![](./images/cluster.png) ![](./images/cluster.jpg)

View file

@ -0,0 +1,23 @@
---
title: 'Hyperion'
lastUpdated: '03.08.2024'
---
## What is it?
Oceanus is my main VM server. It used to be an office PC, but has since been re-purposed as a tiny home server.
## Specs
- MODEL: HP Elitedesk 600 G3
- CPU: i5 6500
- RAM: 16 GB DDR4
- Storage:
- 256 GB NVME SSD
- 128 GB SATA SSD
## What is on it?
This is one of the more powerful nodes in my Proxmox cluster. Mostly used for decent CPU performance tasks.
![](./images/elitedesk_800.jpg)

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 717 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 542 KiB

View file

@ -2,9 +2,9 @@
title: 'Poseidon' title: 'Poseidon'
lastUpdated: '03.08.2024' lastUpdated: '03.08.2024'
--- ---
## What is it?
Poseidon is a node in my cluster of 5 mini PCs. It follows the exact same configuration as the other nodes for consistency. It used to be an office PC, but has since been re-purposed as a tiny home server. Poseidon is a node in my cluster of 5 mini PCs. It follows the exact same configuration as the other nodes for consistency. It used to be an office PC, but has since been re-purposed as a tiny home server.
## Specs
- MODEL: HP Elitedesk 705 G3 mini - MODEL: HP Elitedesk 705 G3 mini
- CPU: AMD A10-8770E - CPU: AMD A10-8770E
- RAM: 16 GB DDR4 - RAM: 16 GB DDR4
@ -21,4 +21,4 @@ This server is running proxmox at the moment, to allow for virtualization of all
- k3s_worker - k3s_worker
- Worker in my K3S cluster - Worker in my K3S cluster
![](./images/cluster.png) ![](./images/cluster.jpg)

View file

@ -22,4 +22,4 @@ This server is running proxmox at the moment, to allow for virtualization of all
- k3s_worker - k3s_worker
- Worker in my K3S cluster - Worker in my K3S cluster
![](./images/cluster.png) ![](./images/cluster.jpg)

View file

@ -42,6 +42,9 @@ const { title, description, pubDate, updatedDate} = Astro.props;
.last-updated-on { .last-updated-on {
font-style: italic; font-style: italic;
} }
img{
align-self: center;
}
</style> </style>
</head> </head>

View file

@ -7,12 +7,12 @@ import Layout from "../layouts/BlogPost.astro";
description="Lorem ipsum dolor sit amet" description="Lorem ipsum dolor sit amet"
pubDate={new Date("08.02.2024")} pubDate={new Date("08.02.2024")}
> >
<p>Hi!</p><p> <p>Hi!</p>
This intoduction thing is not really my style, but first of all my name is <p>
Rolf. My name is Rolf, i am 2024-2000 years old and live in Norway.
</p> </p>
<p> <p>
I currently work as a devops engineer / infrastructure guy. As you probably can tell from this website, front-end is not really my strong suit hehe. I currently work as a devops engineer / infrastructure guy for an insurance company. As you probably can tell from this website, front-end is not really my strong suit hehe.
</p> </p>
<p> <p>
I have a strong love for all things self-hosted. Due to this, i currently run my own "little" homelab from my living room, i use this lab as a learning platform and just an all around I have a strong love for all things self-hosted. Due to this, i currently run my own "little" homelab from my living room, i use this lab as a learning platform and just an all around
@ -21,4 +21,8 @@ import Layout from "../layouts/BlogPost.astro";
<p> <p>
I do love board games! Currently my favorite has to be Magic The Gathering, it eats up way too much of my time and salary, but i find the game so engaging and fun. I do love board games! Currently my favorite has to be Magic The Gathering, it eats up way too much of my time and salary, but i find the game so engaging and fun.
</p> </p>
<p>
I also spend a lot of my time as a member of the student organization <a href="https://fribyte.no">friByte</a>. Even though i am no longer a student, it is hard to quit an orginization with so many dedicated
and nerdy members
</p>
</Layout> </Layout>

View file

@ -7,7 +7,10 @@ import { getCollection } from 'astro:content';
import FormattedDate from '../../components/FormattedDate.astro'; import FormattedDate from '../../components/FormattedDate.astro';
const posts = (await getCollection('blog')).sort( const posts = (await getCollection('blog')).sort(
(a, b) => a.data.pubDate.valueOf() - b.data.pubDate.valueOf() (b, a) => a.data.pubDate.valueOf() - b.data.pubDate.valueOf()
);
const homelab_posts = (await getCollection('homelab')).sort(
(b, a) => a.data.pubDate.valueOf() - b.data.pubDate.valueOf()
); );
--- ---
@ -54,12 +57,12 @@ const posts = (await getCollection('blog')).sort(
} }
.title { .title {
margin: 0; margin: 0;
color: rgb(var(--black)); color: rgb(0,255,159);
line-height: 1; line-height: 1;
} }
.date { .date {
margin: 0; margin: 0;
color: rgb(var(--gray)); color: rgb(white);
} }
ul li a:hover h4, ul li a:hover h4,
ul li a:hover .date { ul li a:hover .date {
@ -83,11 +86,22 @@ const posts = (await getCollection('blog')).sort(
font-size: 1.563em; font-size: 1.563em;
} }
} }
blogheader {
text-align: center;
}
</style> </style>
</head> </head>
<body> <body>
<Header /> <Header />
<main> <main>
<blogheader>
<h1>Blog</h1>
<p>
This page contains a blog about nothing and everything going on with me.
I will probably post mostly random stuff or opinion pieces. What it will be about i have no idea.
So stay tuned!
</p>
</blogheader>
<section> <section>
<ul> <ul>
{ {
@ -102,6 +116,16 @@ const posts = (await getCollection('blog')).sort(
</li> </li>
)) ))
} }
{ homelab_posts.map((post) => (
<li>
<a href={`/homelab/${post.slug}/`}>
<h4 class="title">{post.data.title}</h4>
<p class="date">
<FormattedDate date={post.data.pubDate} />
</p>
</a>
</li>
))}
</ul> </ul>
</section> </section>
</main> </main>

View file

@ -8,9 +8,7 @@ import { SITE_TITLE, SITE_DESCRIPTION } from "../../consts";
const posts = (await getCollection('homelab')).sort(
(a, b) => a.data.pubDate.valueOf() - b.data.pubDate.valueOf()
);
const servers = (await getCollection('servers')); const servers = (await getCollection('servers'));
--- ---
@ -20,31 +18,9 @@ const servers = (await getCollection('servers'));
<BaseHead title={SITE_TITLE} description={SITE_DESCRIPTION} /> <BaseHead title={SITE_TITLE} description={SITE_DESCRIPTION} />
<style> <style>
main { main {
width: 100%; width: 960px;
}
ul {
display: flex;
flex-wrap: wrap;
gap: 2rem;
list-style-type: none;
margin: 0;
padding: 0;
}
ul li {
width: 100%;
}
ul li * {
text-decoration: none;
transition: 0.2s ease;
} }
ul li img {
margin-bottom: 0.5rem;
border-radius: 12px;
}
ul li a {
display: block;
}
.title { .title {
margin: 0; margin: 0;
color: rgb(0,255,159); color: rgb(0,255,159);
@ -54,51 +30,18 @@ const servers = (await getCollection('servers'));
margin: 0; margin: 0;
color: rgb(var(--gray)); color: rgb(var(--gray));
} }
ul li a:hover h4,
ul li a:hover .date {
color: rgb(var(--accent));
}
ul a:hover img {
box-shadow: var(--box-shadow);
}
@media (max-width: 720px) {
ul {
gap: 0.5em;
}
ul li {
width: 100%;
text-align: center;
}
} a {
margin-top: 0.5em;
margin-bottom: 0.5em;
padding: 5px;
}
site_header{ site_header{
text-align: center; text-align: center;
} }
left{
width: 75%;
text-align: center;
}
right{
width: 25%;
text-align: center;
}
#column{
float:left;
}
box{ box{
display: flex; text-align: center;
}
box left,right{
border-color: white;
border-width: 0.2em;
border-style: solid;
border-radius: 1em;
margin: 0.2em;
padding: 0.5em;
} }
</style> </style>
@ -107,11 +50,9 @@ const servers = (await getCollection('servers'));
<Header /> <Header />
<main> <main>
<site_header> <site_header>
<h2>All bout the homelab!</h2> <h2>What is in my homelab now?</h2>
</site_header> </site_header>
<box> <box>
<left class="column">
<h3>What is in my homelab now?</h3>
<p> <p>
So my current homelab has gotten quite extensive, which honestly is a pain because electricity is expensive as hell. So my current homelab has gotten quite extensive, which honestly is a pain because electricity is expensive as hell.
</p> </p>
@ -120,43 +61,15 @@ const servers = (await getCollection('servers'));
let me explain each server, and what it is currently being used for. let me explain each server, and what it is currently being used for.
</p> </p>
<p>As you can probably tell, i use greek mythology for the naming scheme of physical machines :P</p> <p>As you can probably tell, i use greek mythology for the naming scheme of physical machines :P</p>
<section> <box>
<ul>
{ {
servers.map((s) => ( servers.map((s) => (
<li>
<a href={`/homelab/servers/${s.slug}/`}> <a href={`/homelab/servers/${s.slug}/`}>
<h5 class="title">🖥️ {s.data.title}</h5> <h5 class="title">🖥️ {s.data.title}</h5>
</a> </a>
</li>
)) ))
} }
</ul> </box>
</section>
</left>
<right class="column">
<h3>Homelab blog:</h3>
<section>
<ul>
{
posts.length == 0 ? <p>Wow, such empty</p> :
posts.sort((a,b) => {
return b.data.pubDate.getTime() - a.data.pubDate.getTime()
}).map((post) => (
<li>
<a href={`/homelab/${post.slug}/`}>
<h5 class="title">{post.data.title}</h4>
<p class="date">
<FormattedDate date={post.data.pubDate} />
</p>
</a>
</li>
))
}
</ul>
</section>
</right>
</box> </box>
</main> </main>

View file

@ -1,23 +1,64 @@
--- ---
import BaseHead from '../components/BaseHead.astro'; import BaseHead from "../components/BaseHead.astro";
import Header from '../components/Header.astro'; import Header from "../components/Header.astro";
import Footer from '../components/Footer.astro'; import Footer from "../components/Footer.astro";
import { SITE_TITLE, SITE_DESCRIPTION } from '../consts'; import { SITE_TITLE, SITE_DESCRIPTION } from "../consts";
--- ---
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<BaseHead title={SITE_TITLE} description={SITE_DESCRIPTION} /> <BaseHead title={SITE_TITLE} description={SITE_DESCRIPTION} />
</head> <style>
<body> body {
<Header /> text-align: center;
<main> }
<h1>Yo! Welcome to my humble site</h1> main {
<p> }
This site is a continual WIP, and this is just an alpha of what i hope it will become :) main left,
</p> right {
</main> margin: 0.2em;
<Footer /> padding: 0.5em;
</body> }
left {
max-width: 600px;
text-align: center;
}
right {
max-width: 400px;
text-align: center;
}
box {
display: flex;
}
p{
text-align: left;
}
</style>
</head>
<body>
<Header />
<main>
<h1>Rolf Glomsrud</h1>
<img src="images/self.png" />
<h3>Hello!</h3>
<p>Welcome to my little corner of the interwebs, glad to have you!</p>
<p>This site is a little project of mine where is hope to share my adventures both on and off line.</p>
<p>Here are some useful links to my stuff:</p>
<ul>
<li>
<p>I self host my code online using Forgejo! <a href="https://code.polsevev.dev">code.polsevev.dev</a></p>
</li>
<li>
<p>I document my homelab! <a href="/homelab">/homelab</a></p>
</li>
</ul>
</main>
<Footer />
</body>
</html> </html>

View file

@ -4,6 +4,7 @@ import { SITE_TITLE, SITE_DESCRIPTION } from '../consts';
export async function GET(context) { export async function GET(context) {
const posts = await getCollection('blog'); const posts = await getCollection('blog');
const homelab = await getCollection('homelab');
return rss({ return rss({
title: SITE_TITLE, title: SITE_TITLE,
description: SITE_DESCRIPTION, description: SITE_DESCRIPTION,
@ -11,6 +12,9 @@ export async function GET(context) {
items: posts.map((post) => ({ items: posts.map((post) => ({
...post.data, ...post.data,
link: `/blog/${post.slug}/`, link: `/blog/${post.slug}/`,
})), })).concat(homelab.map((post) => ({
...post.data,
link: `/homelab/${post.slug}`
}))),
}); });
} }

View file

@ -30,22 +30,19 @@
font-style: normal; font-style: normal;
font-display: swap; font-display: swap;
} }
html {
height: 100%;
}
footer{
height: 4em;
}
body { body {
font-family: 'Atkinson', sans-serif; font-family: 'Atkinson', sans-serif;
margin: 0; margin: 0;
padding: 0; padding: 0;
min-height: 100vh;
height: 100%; height: 100%;
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
text-align: left; text-align: left;
background: repeating-linear-gradient(to bottom, #522258 0%, #8c3061, #522258 100%); background: repeating-linear-gradient(to bottom, #522258 0%, #8c3061, #522258 100%);
display: flex;
flex-direction: column;
word-wrap: break-word; word-wrap: break-word;
overflow-wrap: break-word; overflow-wrap: break-word;
color: cyan; color: cyan;
@ -54,7 +51,7 @@ body {
} }
@media screen and (min-width:600px) { @media screen and (min-width:600px) {
body { body {
width: 80%; width: 95%;
} }
} }
@media screen and (max-width:600px){ @media screen and (max-width:600px){
@ -63,12 +60,13 @@ body {
} }
} }
main { main {
flex: 1;
width: 720px; width: 720px;
max-width: calc(100% - 2em); max-width: calc(100% - 2em);
margin: auto; margin: auto;
min-height: 100%; min-height: 100%;
padding: 3em 1em; padding: 1em 1em;
margin-bottom: -4em; margin-bottom: -2em;
} }
h1, h1,
h2, h2,
@ -100,10 +98,10 @@ b {
font-weight: 700; font-weight: 700;
} }
a { a {
color: var(--accent); color: white;
} }
a:hover { a:hover {
color: var(--accent); color: black;
} }
p { p {
margin-bottom: 1em; margin-bottom: 1em;
@ -128,8 +126,8 @@ img {
} }
code { code {
padding: 2px 5px; padding: 2px 5px;
background-color: rgb(var(--gray-light)); background-color: black;
border-radius: 2px; border-radius: 10px;
} }
pre { pre {
padding: 1.5em; padding: 1.5em;