adjust frontmatter; new post

This commit is contained in:
Chris W 2023-10-17 13:01:10 -06:00
parent f12d5e7803
commit 4521766aba
13 changed files with 186 additions and 24 deletions

View File

@ -0,0 +1 @@
{}

37
frontmatter.json Normal file
View File

@ -0,0 +1,37 @@
{
"frontMatter.taxonomy.contentTypes": [
{
"name": "default",
"pageBundle": false,
"previewPath": "'blog'",
"filePrefix": null,
"fields": [
{
"title": "Title",
"name": "title",
"type": "string",
"single": true
},
{
"title": "Description",
"name": "description",
"type": "string"
},
{
"title": "Publishing date",
"name": "date",
"type": "datetime",
"default": "{{now}}",
"isPublishDate": true
},
{
"title": "Content preview",
"name": "heroImage",
"type": "image",
"isPreviewImage": true
}
]
}
],
"frontMatter.content.supportedFileTypes": [ "md", "markdown", "mdx" ]
}

3
netlify.toml Normal file
View File

@ -0,0 +1,3 @@
[[redirects]]
from = "/.well-known/webfinger"
to = "/.well-known/webfinger.json"

0
paste69.sql Normal file
View File

View File

@ -8,7 +8,7 @@ export interface Props {
}
export default function Card({ href, frontmatter, secHeading = true }: Props) {
const { title, pubDatetime, description } = frontmatter;
const { title, date, description } = frontmatter;
return (
<li className="my-6">
<a
@ -25,7 +25,7 @@ export default function Card({ href, frontmatter, secHeading = true }: Props) {
</h3>
)}
</a>
<Datetime datetime={pubDatetime} />
<Datetime datetime={date} />
<p>{description}</p>
</li>
);

View File

@ -3,7 +3,7 @@ import { z } from "astro:content";
export const blogSchema = z
.object({
author: z.string().optional(),
pubDatetime: z.date(),
date: z.date(),
title: z.string(),
postSlug: z.string().optional(),
featured: z.boolean().optional(),

View File

@ -1,9 +1,8 @@
---
author: Chris W
pubDatetime: 2022-12-07
date: 2022-12-07
title: An introduction to the Crystal standard library and its core modules
description:
Introducing newcomers to the Crystal standard library and some of the most useful modules contained therein
description: Introducing newcomers to the Crystal standard library and some of the most useful modules contained therein
tags:
- crystal
- programming
@ -32,7 +31,7 @@ puts "Listening on http://127.0.0.1:8080"
server.listen(8080)
```
Running that code will leave you with a very basic server running on port `8080` which will return "Hello world, got _\[some path\]_!" for every path you hit. Of course, using the built-in HTTP server isn't the only way to use Crystal for a website. There are a myriad of options from [Kemal]((https://kemalcr.com/)) and [Grip](https://github.com/grip-framework/grip) which are both very Sinatra/Flask like, to [Lucky](https://luckyframework.org/) which is closer to Rails (not at all in design, but it takes the batteries included approach).
Running that code will leave you with a very basic server running on port `8080` which will return "Hello world, got _\[some path\]_!" for every path you hit. Of course, using the built-in HTTP server isn't the only way to use Crystal for a website. There are a myriad of options from [Kemal](<(https://kemalcr.com/)>) and [Grip](https://github.com/grip-framework/grip) which are both very Sinatra/Flask like, to [Lucky](https://luckyframework.org/) which is closer to Rails (not at all in design, but it takes the batteries included approach).
Of course, the HTTP module would be nothing without
@ -55,7 +54,7 @@ A bit more verbose than I'd prefer, but you can't argue with results.
## JSON
What would a web-centric language be without support for JSON. Now I'm not saying that Crystal is intentionally web-centric, but it is filling a hole that Ruby leaves by being slow as molasses, and Ruby is used *heavily* for web development.
What would a web-centric language be without support for JSON. Now I'm not saying that Crystal is intentionally web-centric, but it is filling a hole that Ruby leaves by being slow as molasses, and Ruby is used _heavily_ for web development.
Working with JSON in statically typed languages can be a massive pain, because JSON is, by its very nature, untyped and kind of unsafe to deal with. Before finding Crystal I loved the way Go handled JSON (de)serialization. As an example for those unfamiliar:

View File

@ -0,0 +1,72 @@
---
author: Chris W
date: 2023-10-17T18:53:50.702Z
title: Migrating your Redis database to another server
description: How to migrate your Redis database to another server using replication
tags:
- redis
- servers
- databases
---
## Table of contents
Seeing this title you might be thinking to yourself, _why would I ever need to do that?_. After all, redis is meant to be used as a throwaway cache right? Caches by their very nature are generally disposable, so what would posess you to want to migrate that cache somewhere else? Well, I can't speak for you, but I can tell you why I needed to do it.
I currently host my own [Firefish](https://joinfirefish.org) instance and have been doing so for the last couple months. In that couple of months I have moved from [Caprover](https://caprover.com), to [Coolify](https://coolify.io), to finally running it in its own VPS. Why all the moving? Because as it turns out, something like Firefish likes to be on its own, especially if you plan on opening your instance up to other people.
Firefish relies on two databases. Postgres for standard data storage, and Redis for caching. The Postgres database is easy enough to migrate, I even wrote a [simple bash script](https://0x45.st/mostly-eventually-themselves.bash) to make it even easier. Redis, however, doesn't have an easy way to dump all of its data to a file, and it doesn't have a way to import that data either. It does have something that might be even easier though.
### Redis replication
Redis has a built-in replication system that allows you to replicate a master database to one or more slave databases. This is useful for a number of reasons, but the one we're interested in is the ability to replicate a database to another server. This is exactly what we need to do in order to migrate our Redis database to another server.
Thankfully this can also be done without editing any configuration files. All you need is access to `redis-cli` on the new server, and a way to connect to the old server. This means that your old server does have to, at least temporarily, be accessible from the outside world (though this can be done over a VPN, or using an internal network). Once you have access to both servers, open a shell in the new server and run the following command:
```bash
redis-cli
```
This will open the redis command line interface. From here we can run the `REPLICAOF` command to tell redis to replicate a master database. The syntax is as follows:
```bash
REPLICAOF <masterip> <masterport>
```
So if your master server is at `10.0.0.2` and is running on port `6379`, you would run the following command:
```bash
REPLICAOF 10.0.0.2 6379
```
This will immediately start the replication process. You can check the status of the replication by running the `INFO` command. This will give you a lot of information, but the part we're interested in is the `master_link_status` field. If this is `up` then the replication is working. If it's `down` then something went wrong.
You can also check the status of the incoming keys by listing all the keys:
```bash
KEYS *
```
This will list all the keys in the database. If you see the keys you expect to see, then the replication is working. If you don't see any keys, then something went wrong.
### Authentication
If you have authentication enabled on your master server via `requirepass`, you'll need to provide the password to the replica server. This can be done by running the following command:
```bash
config set masterauth <password>
```
### Stopping replication
Once you're done with the replication, you can stop it by running the following command:
```bash
REPLICAOF NO ONE
```
This will stop the replication process and allow you to use the replica server as a standalone server. From this point you should be free to delete the master server, or do whatever you want with it.
## Conclusion
I hope this post was helpful to you. I know it's a bit of a niche topic, but I had a hard time finding any information on how to do this, so I figured I'd write it up in case anyone else needs to do this in the future.

View File

@ -77,6 +77,7 @@ const socialImageURL = new URL(
<!-- Matomo -->
<script>
// @ts-ignore
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['trackPageView']);
@ -86,6 +87,7 @@ const socialImageURL = new URL(
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '1']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
// @ts-ignore
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>

View File

@ -13,7 +13,7 @@ export interface Props {
const { post } = Astro.props;
const { title, author, description, ogImage, canonicalURL, pubDatetime, tags } = post.data;
const { title, author, description, ogImage, canonicalURL, date, tags } = post.data;
const { Content } = await post.render();
@ -37,7 +37,7 @@ const ogUrl = new URL(ogImage ? ogImage : `${title}.png`, Astro.url.origin)
</div>
<main id="main-content">
<h1 class="post-title">{title}</h1>
<Datetime datetime={pubDatetime} size="lg" className="my-2" />
<Datetime datetime={date} size="lg" className="my-2" />
<article id="article" role="article" class="prose mx-auto mt-8 max-w-3xl">
<Content />
</article>
@ -45,6 +45,27 @@ const ogUrl = new URL(ogImage ? ogImage : `${title}.png`, Astro.url.origin)
<ul class="tags-container">
{tags.map(tag => <Tag name={slugifyStr(tag)} />)}
</ul>
<div id="coral_thread"></div>
<script type="text/javascript" define:vars={{ canonicalURL, postID: post.id }}>
(function() {
var d = document, s = d.createElement('script');
s.src = 'https://coral.watzon.tech/assets/js/embed.js';
s.async = false;
s.defer = true;
s.onload = function() {
Coral.createStreamEmbed({
id: "coral_thread",
autoRender: true,
rootURL: 'https://coral.watzon.tech',
storyID: `${postID}`,
storyURL: `${canonicalURL}`,
});
};
(d.head || d.body).appendChild(s);
})();
</script>
</main>
<Footer />
</Layout>

View File

@ -15,7 +15,7 @@ export async function get() {
link: `posts/${slugify(data)}`,
title: data.title,
description: data.description,
pubDate: new Date(data.pubDatetime),
pubDate: new Date(data.date),
})),
});
}

View File

@ -0,0 +1,27 @@
export async function get() {
return {
body: JSON.stringify({
subject: "acct:watzon@watzonmanor.com",
aliases: [
"https://watzonmanor.com/@watzon",
"https://watzonmanor.com/users/watzon",
],
links: [
{
rel: "http://webfinger.net/rel/profile-page",
type: "text/html",
href: "https://watzonmanor.com/@watzon",
},
{
rel: "self",
type: "application/activity+json",
href: "https://watzonmanor.com/users/watzon",
},
{
rel: "http://ostatus.org/schema/1.0/subscribe",
template: "https://watzonmanor.com/authorize_interaction?uri={uri}",
},
],
}),
};
}

View File

@ -5,8 +5,8 @@ const getSortedPosts = (posts: CollectionEntry<"blog">[]) =>
.filter(({ data }) => !data.draft)
.sort(
(a, b) =>
Math.floor(new Date(b.data.pubDatetime).getTime() / 1000) -
Math.floor(new Date(a.data.pubDatetime).getTime() / 1000)
Math.floor(new Date(b.data.date).getTime() / 1000) -
Math.floor(new Date(a.data.date).getTime() / 1000)
);
export default getSortedPosts;