From 472e57d2f07f23f5c2b3f11aaf86f750d350d428 Mon Sep 17 00:00:00 2001 From: Daniel LaForce Date: Wed, 23 Apr 2025 01:48:18 -0600 Subject: [PATCH] Refactor project structure and update files --- .astro/collections/blog.schema.json | 130 + .astro/collections/configurations.schema.json | 130 + .astro/collections/external-posts.schema.json | 113 + .astro/collections/posts.schema.json | 130 + .astro/collections/projects.schema.json | 130 + .astro/content-assets.mjs | 1 + .astro/content-modules.mjs | 1 + .astro/content.d.ts | 207 + .astro/data-store.json | 1 + .astro/settings.json | 5 + .astro/types.d.ts | 329 + .env.example | 0 .gitattributes | 25 +- .gitignore | 29 +- SETUP.md | 43 + astro.config.mjs | 26 + astro_files.txt | 36 + backup-20250422/BaseLayout.astro | 112 + backup-20250422/blog-index.astro | 108 + backup-20250422/global.css | 832 ++ backup-20250422/index.astro | 566 + css_files.txt | 58 + package-lock.json | 10342 ++++++++++++++++ package.json | 23 + prisma/schema.prisma | 0 .../images/configs/cloudflare-tunnel.png | Bin .../images/configs/gitops-pipline.png | Bin .../images/configs/k3s-cluster-config.png | Bin .../images/configs/prometheus-monitoring.png | Bin .../images/configs/traefik-config.png | Bin .../images/posts/cloudflare-tunnel-hero.png | Bin .../images/posts/k3installation.png | Bin .../images/posts/prometheusk8.png | Bin .../infrastructure/ha-kubernetes-setup.md | 52 - .../infrastructure/nas-k8s-integration.md | 52 - .../blog/infrastructure/network-security.md | 53 - public/blog/infrastructure/secure-vpn.md | 52 - public/blog/posts/README.md | 27 - public/blog/posts/Test.md | 14 - public/blog/posts/cloudflare-tunnel-setup.md | 180 - public/blog/posts/filebrowser-setup.md | 206 - public/blog/posts/gitea-self-hosted-git.md | 332 - public/blog/posts/gitops-with-flux-cd.md | 169 - public/blog/posts/k3s-cluster.md | 18 - public/blog/posts/k3s-installation-guide.md | 90 - public/blog/posts/prometheus-monitoring.md | 289 - public/blog/posts/proxmox-setup-guide.md | 191 - public/blog/posts/push-blog.sh | 23 - public/blog/posts/quartz-digital-garden.md | 416 - .../posts/rancher-kubernetes-management.md | 328 - .../blog/posts/starting-my-digital-garden.md | 40 - public/blog/posts/test-post.md | 14 - .../posts/vscode-server-remote-development.md | 517 - public/favicon.svg | 9 + public/images/argobox-architecture.svg | 0 public/images/posts/blog-default-hero.jpg | 1 + .../images/posts/cloudflare-tunnel-hero.png | Bin 0 -> 2307359 bytes .../git-symlinks-hero.jpg/k3s-hero-image.jpg | 1 + public/images/posts/k3installation.png | Bin 0 -> 2658672 bytes public/images/posts/k3s-hero-image.jpg | 17 + public/images/posts/prometheusk8.png | Bin 0 -> 2521610 bytes scripts/fetch-images.js | 0 scripts/init-blog-repo.sh | 126 + scripts/process-content-links.sh | 76 +- src/components/404.astro.astro | 372 + src/components/DigitalGardenGraph.astro | 166 + src/components/Footer.astro | 642 + src/components/Header.astro | 438 + src/components/HomePage.astro | 1071 ++ src/components/KnowledgeGraph.astro | 439 + src/components/Newsletter.astro | 0 src/components/PostCard.astro | 53 + src/components/Terminal.astro | 659 + src/content/config.ts | 81 + src/content/config.ts.bak | 79 + .../configurations}/git-symlinks-setup.md | 14 + src/content/external-posts/placeholder.md | 12 - src/content/posts/README.md | 0 src/content/posts/Test.md | 2 +- src/content/posts/cloudflare-tunnel-setup.md | 2 +- src/content/posts/filebrowser-setup.md | 2 +- src/content/posts/gitea-self-hosted-git.md | 2 +- src/content/posts/gitops-with-flux-cd.md | 2 +- src/content/posts/k3s-cluster.md | 93 +- src/content/posts/k3s-installation-guide.md | 2 +- src/content/posts/prometheus-monitoring.md | 359 +- src/content/posts/proxmox-setup-guide.md | 2 +- src/content/posts/push-blog.sh | 23 - src/content/posts/quartz-digital-garden.md | 2 +- .../posts/rancher-kubernetes-management.md | 4 +- .../posts/starting-my-digital-garden.md | 63 +- src/content/posts/test-post.md | 2 +- .../posts/vscode-server-remote-development.md | 2 +- src/content/projects/argobox.md | 53 + src/content/projects/placeholder.md | 0 src/env.d.ts | 1 + src/layouts/BaseLayout.astro | 355 + src/layouts/BlogPost.astro | 575 + src/layouts/BlogPostLayout.astro | 346 + src/pages/api/confirm.ts | 0 src/pages/api/subscribe.ts | 0 src/pages/api/unsubscribe.ts | 0 src/pages/blog/[slug].astro | 38 + src/pages/blog/index.astro | 859 ++ src/pages/categories/[category].astro | 0 src/pages/categories/index.astro | 0 src/pages/configurations.astro | 0 src/pages/configurations/[slug].astro | 0 src/pages/index.astro | 816 ++ src/pages/posts/[slug].astro | 17 + src/pages/projects/[slug].astro | 0 src/pages/search.astro | 259 + src/pages/stack.astro | 0 src/pages/subscription-confirmed.astro | 0 src/pages/tag/[tag].astro | 263 + src/pages/tags/index.astro | 130 + src/pages/unsubscribe.astro | 0 src/styles/global.css | 1155 ++ src/utils/newsletter-config.ts | 0 src/utils/newsletter.ts | 0 style_files.txt | 58 + sync-obsidian.sh | 53 + tailwind.config.js | 34 + tsconfig.json | 11 + 124 files changed, 22896 insertions(+), 3385 deletions(-) create mode 100644 .astro/collections/blog.schema.json create mode 100644 .astro/collections/configurations.schema.json create mode 100644 .astro/collections/external-posts.schema.json create mode 100644 .astro/collections/posts.schema.json create mode 100644 .astro/collections/projects.schema.json create mode 100644 .astro/content-assets.mjs create mode 100644 .astro/content-modules.mjs create mode 100644 .astro/content.d.ts create mode 100644 .astro/data-store.json create mode 100644 .astro/settings.json create mode 100644 .astro/types.d.ts create mode 100644 .env.example create mode 100644 SETUP.md create mode 100644 astro.config.mjs create mode 100644 astro_files.txt create mode 100644 backup-20250422/BaseLayout.astro create mode 100644 backup-20250422/blog-index.astro create mode 100644 backup-20250422/global.css create mode 100644 backup-20250422/index.astro create mode 100644 css_files.txt create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 prisma/schema.prisma rename public/{blog => assets}/images/configs/cloudflare-tunnel.png (100%) mode change 100755 => 100644 rename public/{blog => assets}/images/configs/gitops-pipline.png (100%) mode change 100755 => 100644 rename public/{blog => assets}/images/configs/k3s-cluster-config.png (100%) mode change 100755 => 100644 rename public/{blog => assets}/images/configs/prometheus-monitoring.png (100%) mode change 100755 => 100644 rename public/{blog => assets}/images/configs/traefik-config.png (100%) mode change 100755 => 100644 rename public/{blog => assets}/images/posts/cloudflare-tunnel-hero.png (100%) mode change 100755 => 100644 rename public/{blog => assets}/images/posts/k3installation.png (100%) mode change 100755 => 100644 rename public/{blog => assets}/images/posts/prometheusk8.png (100%) mode change 100755 => 100644 delete mode 100755 public/blog/infrastructure/ha-kubernetes-setup.md delete mode 100755 public/blog/infrastructure/nas-k8s-integration.md delete mode 100755 public/blog/infrastructure/network-security.md delete mode 100755 public/blog/infrastructure/secure-vpn.md delete mode 100755 public/blog/posts/README.md delete mode 100755 public/blog/posts/Test.md delete mode 100755 public/blog/posts/cloudflare-tunnel-setup.md delete mode 100755 public/blog/posts/filebrowser-setup.md delete mode 100755 public/blog/posts/gitea-self-hosted-git.md delete mode 100755 public/blog/posts/gitops-with-flux-cd.md delete mode 100755 public/blog/posts/k3s-cluster.md delete mode 100755 public/blog/posts/k3s-installation-guide.md delete mode 100755 public/blog/posts/prometheus-monitoring.md delete mode 100755 public/blog/posts/proxmox-setup-guide.md delete mode 100755 public/blog/posts/push-blog.sh delete mode 100755 public/blog/posts/quartz-digital-garden.md delete mode 100755 public/blog/posts/rancher-kubernetes-management.md delete mode 100755 public/blog/posts/starting-my-digital-garden.md delete mode 100755 public/blog/posts/test-post.md delete mode 100755 public/blog/posts/vscode-server-remote-development.md create mode 100644 public/favicon.svg create mode 100644 public/images/argobox-architecture.svg create mode 100644 public/images/posts/blog-default-hero.jpg create mode 100644 public/images/posts/cloudflare-tunnel-hero.png create mode 100644 public/images/posts/git-symlinks-hero.jpg/k3s-hero-image.jpg create mode 100644 public/images/posts/k3installation.png create mode 100644 public/images/posts/k3s-hero-image.jpg create mode 100644 public/images/posts/prometheusk8.png create mode 100644 scripts/fetch-images.js create mode 100644 scripts/init-blog-repo.sh mode change 100755 => 100644 scripts/process-content-links.sh create mode 100644 src/components/404.astro.astro create mode 100644 src/components/DigitalGardenGraph.astro create mode 100644 src/components/Footer.astro create mode 100644 src/components/Header.astro create mode 100644 src/components/HomePage.astro create mode 100644 src/components/KnowledgeGraph.astro create mode 100644 src/components/Newsletter.astro create mode 100644 src/components/PostCard.astro create mode 100644 src/components/Terminal.astro create mode 100644 src/content/config.ts create mode 100644 src/content/config.ts.bak rename {public/blog/configs => src/content/configurations}/git-symlinks-setup.md (95%) mode change 100755 => 100644 delete mode 100755 src/content/external-posts/placeholder.md mode change 100755 => 100644 src/content/posts/README.md mode change 100755 => 100644 src/content/posts/Test.md mode change 100755 => 100644 src/content/posts/cloudflare-tunnel-setup.md mode change 100755 => 100644 src/content/posts/filebrowser-setup.md mode change 100755 => 100644 src/content/posts/gitea-self-hosted-git.md mode change 100755 => 100644 src/content/posts/gitops-with-flux-cd.md mode change 100755 => 100644 src/content/posts/k3s-cluster.md mode change 100755 => 100644 src/content/posts/k3s-installation-guide.md mode change 100755 => 100644 src/content/posts/prometheus-monitoring.md mode change 100755 => 100644 src/content/posts/proxmox-setup-guide.md delete mode 100755 src/content/posts/push-blog.sh mode change 100755 => 100644 src/content/posts/quartz-digital-garden.md mode change 100755 => 100644 src/content/posts/rancher-kubernetes-management.md mode change 100755 => 100644 src/content/posts/starting-my-digital-garden.md mode change 100755 => 100644 src/content/posts/test-post.md mode change 100755 => 100644 src/content/posts/vscode-server-remote-development.md mode change 100755 => 100644 src/content/projects/argobox.md mode change 100755 => 100644 src/content/projects/placeholder.md create mode 100644 src/env.d.ts create mode 100644 src/layouts/BaseLayout.astro create mode 100644 src/layouts/BlogPost.astro create mode 100644 src/layouts/BlogPostLayout.astro create mode 100644 src/pages/api/confirm.ts create mode 100644 src/pages/api/subscribe.ts create mode 100644 src/pages/api/unsubscribe.ts create mode 100644 src/pages/blog/[slug].astro create mode 100644 src/pages/blog/index.astro create mode 100644 src/pages/categories/[category].astro create mode 100644 src/pages/categories/index.astro create mode 100644 src/pages/configurations.astro create mode 100644 src/pages/configurations/[slug].astro create mode 100644 src/pages/index.astro create mode 100644 src/pages/posts/[slug].astro create mode 100644 src/pages/projects/[slug].astro create mode 100644 src/pages/search.astro create mode 100644 src/pages/stack.astro create mode 100644 src/pages/subscription-confirmed.astro create mode 100644 src/pages/tag/[tag].astro create mode 100644 src/pages/tags/index.astro create mode 100644 src/pages/unsubscribe.astro create mode 100644 src/styles/global.css create mode 100644 src/utils/newsletter-config.ts create mode 100644 src/utils/newsletter.ts create mode 100644 style_files.txt create mode 100644 sync-obsidian.sh create mode 100644 tailwind.config.js create mode 100644 tsconfig.json diff --git a/.astro/collections/blog.schema.json b/.astro/collections/blog.schema.json new file mode 100644 index 0000000..0541077 --- /dev/null +++ b/.astro/collections/blog.schema.json @@ -0,0 +1,130 @@ +{ + "$ref": "#/definitions/blog", + "definitions": { + "blog": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "pubDate": { + "anyOf": [ + { + "type": "string" + }, + { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "string", + "format": "date" + }, + { + "type": "integer", + "format": "unix-time" + } + ] + }, + { + "type": "null" + } + ] + }, + "updatedDate": { + "anyOf": [ + { + "type": "string" + }, + { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "string", + "format": "date" + }, + { + "type": "integer", + "format": "unix-time" + } + ] + }, + { + "type": "null" + } + ] + }, + "heroImage": { + "anyOf": [ + { + "anyOf": [ + { + "not": {} + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ] + }, + "category": { + "type": "string" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + } + }, + "draft": { + "type": "boolean" + }, + "readTime": { + "type": "string" + }, + "image": { + "type": "string" + }, + "excerpt": { + "type": "string" + }, + "author": { + "type": "string" + }, + "github": { + "type": "string" + }, + "live": { + "type": "string" + }, + "technologies": { + "type": "array", + "items": { + "type": "string" + } + }, + "$schema": { + "type": "string" + } + }, + "required": [ + "title", + "pubDate" + ], + "additionalProperties": true + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/.astro/collections/configurations.schema.json b/.astro/collections/configurations.schema.json new file mode 100644 index 0000000..3b5a03b --- /dev/null +++ b/.astro/collections/configurations.schema.json @@ -0,0 +1,130 @@ +{ + "$ref": "#/definitions/configurations", + "definitions": { + "configurations": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "pubDate": { + "anyOf": [ + { + "type": "string" + }, + { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "string", + "format": "date" + }, + { + "type": "integer", + "format": "unix-time" + } + ] + }, + { + "type": "null" + } + ] + }, + "updatedDate": { + "anyOf": [ + { + "type": "string" + }, + { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "string", + "format": "date" + }, + { + "type": "integer", + "format": "unix-time" + } + ] + }, + { + "type": "null" + } + ] + }, + "heroImage": { + "anyOf": [ + { + "anyOf": [ + { + "not": {} + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ] + }, + "category": { + "type": "string" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + } + }, + "draft": { + "type": "boolean" + }, + "readTime": { + "type": "string" + }, + "image": { + "type": "string" + }, + "excerpt": { + "type": "string" + }, + "author": { + "type": "string" + }, + "github": { + "type": "string" + }, + "live": { + "type": "string" + }, + "technologies": { + "type": "array", + "items": { + "type": "string" + } + }, + "$schema": { + "type": "string" + } + }, + "required": [ + "title", + "pubDate" + ], + "additionalProperties": true + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/.astro/collections/external-posts.schema.json b/.astro/collections/external-posts.schema.json new file mode 100644 index 0000000..d162d08 --- /dev/null +++ b/.astro/collections/external-posts.schema.json @@ -0,0 +1,113 @@ +{ + "$ref": "#/definitions/external-posts", + "definitions": { + "external-posts": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "pubDate": { + "anyOf": [ + { + "type": "string" + }, + { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "string", + "format": "date" + }, + { + "type": "integer", + "format": "unix-time" + } + ] + } + ] + }, + "updatedDate": { + "anyOf": [ + { + "type": "string" + }, + { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "string", + "format": "date" + }, + { + "type": "integer", + "format": "unix-time" + } + ] + } + ] + }, + "heroImage": { + "type": "string" + }, + "category": { + "type": "string", + "default": "Uncategorized" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "draft": { + "type": "boolean", + "default": false + }, + "readTime": { + "type": "string" + }, + "image": { + "type": "string" + }, + "excerpt": { + "type": "string" + }, + "author": { + "type": "string" + }, + "github": { + "type": "string" + }, + "live": { + "type": "string" + }, + "technologies": { + "type": "array", + "items": { + "type": "string" + } + }, + "$schema": { + "type": "string" + } + }, + "required": [ + "title", + "pubDate" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/.astro/collections/posts.schema.json b/.astro/collections/posts.schema.json new file mode 100644 index 0000000..6d8a7a3 --- /dev/null +++ b/.astro/collections/posts.schema.json @@ -0,0 +1,130 @@ +{ + "$ref": "#/definitions/posts", + "definitions": { + "posts": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "pubDate": { + "anyOf": [ + { + "type": "string" + }, + { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "string", + "format": "date" + }, + { + "type": "integer", + "format": "unix-time" + } + ] + }, + { + "type": "null" + } + ] + }, + "updatedDate": { + "anyOf": [ + { + "type": "string" + }, + { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "string", + "format": "date" + }, + { + "type": "integer", + "format": "unix-time" + } + ] + }, + { + "type": "null" + } + ] + }, + "heroImage": { + "anyOf": [ + { + "anyOf": [ + { + "not": {} + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ] + }, + "category": { + "type": "string" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + } + }, + "draft": { + "type": "boolean" + }, + "readTime": { + "type": "string" + }, + "image": { + "type": "string" + }, + "excerpt": { + "type": "string" + }, + "author": { + "type": "string" + }, + "github": { + "type": "string" + }, + "live": { + "type": "string" + }, + "technologies": { + "type": "array", + "items": { + "type": "string" + } + }, + "$schema": { + "type": "string" + } + }, + "required": [ + "title", + "pubDate" + ], + "additionalProperties": true + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/.astro/collections/projects.schema.json b/.astro/collections/projects.schema.json new file mode 100644 index 0000000..fdb83de --- /dev/null +++ b/.astro/collections/projects.schema.json @@ -0,0 +1,130 @@ +{ + "$ref": "#/definitions/projects", + "definitions": { + "projects": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "pubDate": { + "anyOf": [ + { + "type": "string" + }, + { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "string", + "format": "date" + }, + { + "type": "integer", + "format": "unix-time" + } + ] + }, + { + "type": "null" + } + ] + }, + "updatedDate": { + "anyOf": [ + { + "type": "string" + }, + { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "string", + "format": "date" + }, + { + "type": "integer", + "format": "unix-time" + } + ] + }, + { + "type": "null" + } + ] + }, + "heroImage": { + "anyOf": [ + { + "anyOf": [ + { + "not": {} + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ] + }, + "category": { + "type": "string" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + } + }, + "draft": { + "type": "boolean" + }, + "readTime": { + "type": "string" + }, + "image": { + "type": "string" + }, + "excerpt": { + "type": "string" + }, + "author": { + "type": "string" + }, + "github": { + "type": "string" + }, + "live": { + "type": "string" + }, + "technologies": { + "type": "array", + "items": { + "type": "string" + } + }, + "$schema": { + "type": "string" + } + }, + "required": [ + "title", + "pubDate" + ], + "additionalProperties": true + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/.astro/content-assets.mjs b/.astro/content-assets.mjs new file mode 100644 index 0000000..2b8b823 --- /dev/null +++ b/.astro/content-assets.mjs @@ -0,0 +1 @@ +export default new Map(); \ No newline at end of file diff --git a/.astro/content-modules.mjs b/.astro/content-modules.mjs new file mode 100644 index 0000000..2b8b823 --- /dev/null +++ b/.astro/content-modules.mjs @@ -0,0 +1 @@ +export default new Map(); \ No newline at end of file diff --git a/.astro/content.d.ts b/.astro/content.d.ts new file mode 100644 index 0000000..22643e8 --- /dev/null +++ b/.astro/content.d.ts @@ -0,0 +1,207 @@ +declare module 'astro:content' { + interface Render { + '.mdx': Promise<{ + Content: import('astro').MarkdownInstance<{}>['Content']; + headings: import('astro').MarkdownHeading[]; + remarkPluginFrontmatter: Record; + components: import('astro').MDXInstance<{}>['components']; + }>; + } +} + +declare module 'astro:content' { + export interface RenderResult { + Content: import('astro/runtime/server/index.js').AstroComponentFactory; + headings: import('astro').MarkdownHeading[]; + remarkPluginFrontmatter: Record; + } + interface Render { + '.md': Promise; + } + + export interface RenderedContent { + html: string; + metadata?: { + imagePaths: Array; + [key: string]: unknown; + }; + } +} + +declare module 'astro:content' { + type Flatten = T extends { [K: string]: infer U } ? U : never; + + export type CollectionKey = keyof AnyEntryMap; + export type CollectionEntry = Flatten; + + export type ContentCollectionKey = keyof ContentEntryMap; + export type DataCollectionKey = keyof DataEntryMap; + + type AllValuesOf = T extends any ? T[keyof T] : never; + type ValidContentEntrySlug = AllValuesOf< + ContentEntryMap[C] + >['slug']; + + export type ReferenceDataEntry< + C extends CollectionKey, + E extends keyof DataEntryMap[C] = string, + > = { + collection: C; + id: E; + }; + export type ReferenceContentEntry< + C extends keyof ContentEntryMap, + E extends ValidContentEntrySlug | (string & {}) = string, + > = { + collection: C; + slug: E; + }; + + /** @deprecated Use `getEntry` instead. */ + export function getEntryBySlug< + C extends keyof ContentEntryMap, + E extends ValidContentEntrySlug | (string & {}), + >( + collection: C, + // Note that this has to accept a regular string too, for SSR + entrySlug: E, + ): E extends ValidContentEntrySlug + ? Promise> + : Promise | undefined>; + + /** @deprecated Use `getEntry` instead. */ + export function getDataEntryById( + collection: C, + entryId: E, + ): Promise>; + + export function getCollection>( + collection: C, + filter?: (entry: CollectionEntry) => entry is E, + ): Promise; + export function getCollection( + collection: C, + filter?: (entry: CollectionEntry) => unknown, + ): Promise[]>; + + export function getEntry< + C extends keyof ContentEntryMap, + E extends ValidContentEntrySlug | (string & {}), + >( + entry: ReferenceContentEntry, + ): E extends ValidContentEntrySlug + ? Promise> + : Promise | undefined>; + export function getEntry< + C extends keyof DataEntryMap, + E extends keyof DataEntryMap[C] | (string & {}), + >( + entry: ReferenceDataEntry, + ): E extends keyof DataEntryMap[C] + ? Promise + : Promise | undefined>; + export function getEntry< + C extends keyof ContentEntryMap, + E extends ValidContentEntrySlug | (string & {}), + >( + collection: C, + slug: E, + ): E extends ValidContentEntrySlug + ? Promise> + : Promise | undefined>; + export function getEntry< + C extends keyof DataEntryMap, + E extends keyof DataEntryMap[C] | (string & {}), + >( + collection: C, + id: E, + ): E extends keyof DataEntryMap[C] + ? string extends keyof DataEntryMap[C] + ? Promise | undefined + : Promise + : Promise | undefined>; + + /** Resolve an array of entry references from the same collection */ + export function getEntries( + entries: ReferenceContentEntry>[], + ): Promise[]>; + export function getEntries( + entries: ReferenceDataEntry[], + ): Promise[]>; + + export function render( + entry: AnyEntryMap[C][string], + ): Promise; + + export function reference( + collection: C, + ): import('astro/zod').ZodEffects< + import('astro/zod').ZodString, + C extends keyof ContentEntryMap + ? ReferenceContentEntry> + : ReferenceDataEntry + >; + // Allow generic `string` to avoid excessive type errors in the config + // if `dev` is not running to update as you edit. + // Invalid collection names will be caught at build time. + export function reference( + collection: C, + ): import('astro/zod').ZodEffects; + + type ReturnTypeOrOriginal = T extends (...args: any[]) => infer R ? R : T; + type InferEntrySchema = import('astro/zod').infer< + ReturnTypeOrOriginal['schema']> + >; + + type ContentEntryMap = { + + }; + + type DataEntryMap = { + "blog": Record; + rendered?: RenderedContent; + filePath?: string; +}>; +"configurations": Record; + rendered?: RenderedContent; + filePath?: string; +}>; +"posts": Record; + rendered?: RenderedContent; + filePath?: string; +}>; +"projects": Record; + rendered?: RenderedContent; + filePath?: string; +}>; + + }; + + type AnyEntryMap = ContentEntryMap & DataEntryMap; + + export type ContentConfig = typeof import("../src/content/config.js"); +} diff --git a/.astro/data-store.json b/.astro/data-store.json new file mode 100644 index 0000000..78ca46e --- /dev/null +++ b/.astro/data-store.json @@ -0,0 +1 @@ +[["Map",1,2,9,10,1896,1897,1933,1934,2406,2407],"meta::meta",["Map",3,4,5,6,7,8],"astro-version","5.7.4","content-config-digest","fa3611ab1618c2d2","astro-config-digest","{\"root\":{},\"srcDir\":{},\"publicDir\":{},\"outDir\":{},\"cacheDir\":{},\"site\":\"https://laforceit.blog\",\"compressHTML\":true,\"base\":\"/\",\"trailingSlash\":\"ignore\",\"output\":\"static\",\"scopedStyleStrategy\":\"attribute\",\"build\":{\"format\":\"directory\",\"client\":{},\"server\":{},\"assets\":\"_astro\",\"serverEntry\":\"index.js\",\"redirects\":false,\"inlineStylesheets\":\"auto\",\"concurrency\":1},\"server\":{\"open\":false,\"host\":true,\"port\":4321,\"streaming\":true,\"allowedHosts\":[]},\"redirects\":{},\"image\":{\"endpoint\":{\"route\":\"/_image\"},\"service\":{\"entrypoint\":\"astro/assets/services/sharp\",\"config\":{}},\"domains\":[],\"remotePatterns\":[]},\"devToolbar\":{\"enabled\":true},\"markdown\":{\"syntaxHighlight\":{\"type\":\"shiki\",\"excludeLangs\":[\"math\"]},\"shikiConfig\":{\"langs\":[],\"langAlias\":{},\"theme\":\"dracula\",\"themes\":{},\"wrap\":true,\"transformers\":[]},\"remarkPlugins\":[],\"rehypePlugins\":[],\"remarkRehype\":{},\"gfm\":true,\"smartypants\":true},\"security\":{\"checkOrigin\":true},\"env\":{\"schema\":{},\"validateSecrets\":false},\"experimental\":{\"clientPrerender\":false,\"contentIntellisense\":false,\"responsiveImages\":false,\"headingIdCompat\":false,\"preserveScriptOrder\":false},\"legacy\":{\"collections\":false},\"session\":{\"driver\":\"fs-lite\",\"options\":{\"base\":\"/home/argonaut/Projects/laforceit-blog/.astro/integrations/_astrojs_cloudflare/sessions\"}}}","blog",["Map",11,12,37,38,67,68,171,172,216,217,260,261,312,313,379,380,439,440,477,478,500,501,573,574,627,628,701,702,818,819,891,892,919,920,944,945,969,970,993,994,1015,1016,1040,1041,1065,1066,1088,1089,1111,1112,1134,1135,1151,1152,1165,1166,1187,1188,1230,1231,1272,1273,1297,1298,1324,1325,1390,1391,1422,1423,1498,1499,1526,1527,1560,1561,1592,1593,1609,1610,1648,1649,1748,1749,1772,1773,1810,1811,1858,1859],"test",{"id":11,"data":13,"filePath":25,"digest":26,"rendered":27,"legacyId":36},{"title":14,"description":15,"pubDate":16,"heroImage":17,"category":18,"tags":19,"readTime":24},"Secure Remote Access with Cloudflare Tunnels","How to set up Cloudflare Tunnels for secure remote access to your home lab services","Jul 22 2023","/blog/images/posts/prometheusk8.png","networking",[20,18,21,22,23],"cloudflare","security","homelab","tunnels","7 min read","src/content/blog/Test.md","48a370d6e87745b0",{"html":28,"metadata":29},"",{"headings":30,"localImagePaths":31,"remoteImagePaths":32,"frontmatter":33,"imagePaths":35},[],[],[],{"title":14,"description":15,"pubDate":16,"heroImage":17,"category":18,"tags":34,"readTime":24},[20,18,21,22,23],[],"Test.md","readme",{"id":37,"data":39,"body":44,"filePath":45,"digest":46,"rendered":47,"legacyId":66},{"title":40,"description":41,"pubDate":42,"draft":43},"Blog Posts Collection","Documentation for blog posts",["Date","2025-04-18T00:00:00.000Z"],true,"# Blog Posts Collection\n\nThis directory contains blog posts for the LaForceIT digital garden.\n\n## Content Guidelines\n\n- All posts should include proper frontmatter\n- Use Markdown for formatting content\n- Images should be placed in the public/blog/images directory\n\n## Frontmatter Requirements\n\nEvery post needs at minimum:\n\n```\n---\ntitle: \"Post Title\" \npubDate: YYYY-MM-DD\n---\n```","src/content/blog/README.md","a6b53d4675b8cf53",{"html":48,"metadata":49},"\u003Ch1 id=\"blog-posts-collection\">Blog Posts Collection\u003C/h1>\n\u003Cp>This directory contains blog posts for the LaForceIT digital garden.\u003C/p>\n\u003Ch2 id=\"content-guidelines\">Content Guidelines\u003C/h2>\n\u003Cul>\n\u003Cli>All posts should include proper frontmatter\u003C/li>\n\u003Cli>Use Markdown for formatting content\u003C/li>\n\u003Cli>Images should be placed in the public/blog/images directory\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"frontmatter-requirements\">Frontmatter Requirements\u003C/h2>\n\u003Cp>Every post needs at minimum:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"plaintext\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan>---\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>title: \"Post Title\" \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>pubDate: YYYY-MM-DD\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>---\u003C/span>\u003C/span>\u003C/code>\u003C/pre>",{"headings":50,"localImagePaths":61,"remoteImagePaths":62,"frontmatter":63,"imagePaths":65},[51,54,58],{"depth":52,"slug":53,"text":40},1,"blog-posts-collection",{"depth":55,"slug":56,"text":57},2,"content-guidelines","Content Guidelines",{"depth":55,"slug":59,"text":60},"frontmatter-requirements","Frontmatter Requirements",[],[],{"title":40,"description":41,"pubDate":64,"draft":43},["Date","2025-04-18T00:00:00.000Z"],[],"README.md","proxmox-setup-guide",{"id":67,"data":69,"body":78,"filePath":79,"digest":80,"rendered":81,"legacyId":170},{"title":70,"description":71,"pubDate":72,"heroImage":17,"category":73,"tags":74,"readTime":77},"Complete Proxmox VE Setup Guide","A step-by-step guide to setting up Proxmox VE for your home lab virtualization needs",["Date","2025-04-19T00:00:00.000Z"],"infrastructure",[75,76,22,73],"proxmox","virtualization","12 min read","# Complete Proxmox VE Setup Guide\n\nProxmox Virtual Environment (VE) is a complete open-source server management platform for enterprise virtualization. It tightly integrates KVM hypervisor and LXC containers, software-defined storage and networking functionality, on a single platform. This guide will walk you through installing and configuring Proxmox VE for your home lab.\n\n## Why Choose Proxmox VE?\n\n- **Open Source**: Free to use with optional paid enterprise support\n- **Full-featured**: Combines KVM hypervisor and LXC containers\n- **Web Interface**: Easy-to-use management interface\n- **Clustering**: Built-in high availability features\n- **Storage Flexibility**: Support for local, SAN, NFS, Ceph, and more\n\n## Hardware Requirements\n\n- 64-bit CPU with virtualization extensions (Intel VT-x/AMD-V)\n- At least 2GB RAM (8GB+ recommended)\n- Hard drive for OS installation (SSD recommended)\n- Additional storage for VMs and containers\n- Network interface card\n\n## Installation\n\n### 1. Prepare for Installation\n\n1. Download the Proxmox VE ISO from [proxmox.com/downloads](https://www.proxmox.com/downloads)\n2. Create a bootable USB drive using tools like Rufus, Etcher, or dd\n3. Ensure virtualization is enabled in your BIOS/UEFI\n\n### 2. Install Proxmox VE\n\n1. Boot from the USB drive\n2. Select \"Install Proxmox VE\"\n3. Accept the EULA\n4. Select the target hard drive (this will erase all data on the drive)\n5. Configure country, time zone, and keyboard layout\n6. Set a strong root password and provide an email address\n7. Configure network settings:\n - Enter a hostname (FQDN format: proxmox.yourdomain.local)\n - IP address, netmask, gateway\n - DNS server\n8. Review the settings and confirm to start the installation\n9. Once completed, remove the USB drive and reboot\n\n### 3. Initial Configuration\n\nAccess the web interface by navigating to `https://\u003Cyour-proxmox-ip>:8006` in your browser. Log in with:\n- Username: root\n- Password: (the one you set during installation)\n\n## Post-Installation Tasks\n\n### 1. Update Proxmox VE\n\n```bash\napt update\napt dist-upgrade\n```\n\n### 2. Remove Subscription Notice (Optional)\n\nFor home lab use, you can remove the subscription notice:\n\n```bash\necho \"DPkg::Post-Invoke { \\\"dpkg -V proxmox-widget-toolkit | grep -q '/proxmoxlib\\.js$'; if [ \\$? -eq 1 ]; then { echo 'Removing subscription nag from UI...'; sed -i '/.*data\\.status.*subscription.*/d' /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js; }; fi\\\"; };\" > /etc/apt/apt.conf.d/no-subscription-warning\n```\n\n### 3. Configure Storage\n\n#### Local Storage\n\nBy default, Proxmox VE creates several storage locations:\n\n- **local**: For ISO images, container templates, and snippets\n- **local-lvm**: For VM disk images\n\nTo add a new storage, go to Datacenter > Storage > Add:\n\n- For local directories: Select \"Directory\"\n- For network storage: Select \"NFS\" or \"CIFS\"\n- For block storage: Select \"LVM\", \"LVM-Thin\", or \"ZFS\"\n\n#### ZFS Storage Pool (Recommended)\n\nZFS offers excellent performance and data protection:\n\n```bash\n# Create a ZFS pool using available disks\nzpool create -f rpool /dev/sdb /dev/sdc\n\n# Add the pool to Proxmox\npvesm add zfspool rpool -pool rpool\n```\n\n### 4. Set Up Networking\n\n#### Network Bridges\n\nProxmox VE creates a default bridge (vmbr0) during installation. To add more:\n\n1. Go to Node > Network > Create > Linux Bridge\n2. Configure the bridge:\n - Name: vmbr1\n - IP address/CIDR: 192.168.1.1/24 (or leave empty for unmanaged bridge)\n - Bridge ports: (physical interface, e.g., eth1)\n\n#### VLAN Configuration\n\nFor VLAN support:\n\n1. Ensure the bridge has VLAN awareness enabled\n2. In VM network settings, specify VLAN tags \n\n## Creating Virtual Machines and Containers\n\n### Virtual Machines (KVM)\n\n1. Go to Create VM\n2. Fill out the wizard:\n - General: Name, Resource Pool\n - OS: ISO image, type, and version\n - System: BIOS/UEFI, Machine type\n - Disks: Size, format, storage location\n - CPU: Cores, type\n - Memory: RAM size\n - Network: Bridge, model\n3. Click Finish to create the VM\n\n### Containers (LXC)\n\n1. Go to Create CT\n2. Fill out the wizard:\n - General: Hostname, Password\n - Template: Select from available templates\n - Disks: Size, storage location\n - CPU: Cores\n - Memory: RAM size\n - Network: IP address, bridge\n - DNS: DNS servers\n3. Click Finish to create the container\n\n## Backup Configuration\n\n### Setting Up Backups\n\n1. Go to Datacenter > Backup\n2. Add a new backup job:\n - Select storage location\n - Set schedule (daily, weekly, etc.)\n - Choose VMs/containers to back up\n - Configure compression and mode\n\n## Performance Tuning\n\n### CPU\n\nFor VMs that need consistent performance:\n\n- Set CPU type to \"host\" for best performance\n- Reserve CPU cores for critical VMs\n- Use CPU pinning for high-performance workloads\n\n### Memory\n\n- Enable KSM (Kernel Same-page Merging) for better memory usage\n- Set appropriate memory ballooning for VMs\n\n### Storage\n\n- Use SSDs for VM disks when possible\n- Enable write-back caching for improved performance\n- Consider ZFS for important data with appropriate RAM allocation\n\n## Conclusion\n\nProxmox VE is a powerful, flexible virtualization platform perfect for home labs. With its combination of virtual machines and containers, you can build a versatile lab environment for testing, development, and running production services.\n\nAfter following this guide, you should have a fully functional Proxmox VE server ready to host your virtual infrastructure. In future articles, we'll explore advanced topics like clustering, high availability, and integration with other infrastructure tools.","src/content/blog/proxmox-setup-guide.md","e4a22cbeb05f2611",{"html":82,"metadata":83},"\u003Ch1 id=\"complete-proxmox-ve-setup-guide\">Complete Proxmox VE Setup Guide\u003C/h1>\n\u003Cp>Proxmox Virtual Environment (VE) is a complete open-source server management platform for enterprise virtualization. It tightly integrates KVM hypervisor and LXC containers, software-defined storage and networking functionality, on a single platform. This guide will walk you through installing and configuring Proxmox VE for your home lab.\u003C/p>\n\u003Ch2 id=\"why-choose-proxmox-ve\">Why Choose Proxmox VE?\u003C/h2>\n\u003Cul>\n\u003Cli>\u003Cstrong>Open Source\u003C/strong>: Free to use with optional paid enterprise support\u003C/li>\n\u003Cli>\u003Cstrong>Full-featured\u003C/strong>: Combines KVM hypervisor and LXC containers\u003C/li>\n\u003Cli>\u003Cstrong>Web Interface\u003C/strong>: Easy-to-use management interface\u003C/li>\n\u003Cli>\u003Cstrong>Clustering\u003C/strong>: Built-in high availability features\u003C/li>\n\u003Cli>\u003Cstrong>Storage Flexibility\u003C/strong>: Support for local, SAN, NFS, Ceph, and more\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"hardware-requirements\">Hardware Requirements\u003C/h2>\n\u003Cul>\n\u003Cli>64-bit CPU with virtualization extensions (Intel VT-x/AMD-V)\u003C/li>\n\u003Cli>At least 2GB RAM (8GB+ recommended)\u003C/li>\n\u003Cli>Hard drive for OS installation (SSD recommended)\u003C/li>\n\u003Cli>Additional storage for VMs and containers\u003C/li>\n\u003Cli>Network interface card\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"installation\">Installation\u003C/h2>\n\u003Ch3 id=\"1-prepare-for-installation\">1. Prepare for Installation\u003C/h3>\n\u003Col>\n\u003Cli>Download the Proxmox VE ISO from \u003Ca href=\"https://www.proxmox.com/downloads\">proxmox.com/downloads\u003C/a>\u003C/li>\n\u003Cli>Create a bootable USB drive using tools like Rufus, Etcher, or dd\u003C/li>\n\u003Cli>Ensure virtualization is enabled in your BIOS/UEFI\u003C/li>\n\u003C/ol>\n\u003Ch3 id=\"2-install-proxmox-ve\">2. Install Proxmox VE\u003C/h3>\n\u003Col>\n\u003Cli>Boot from the USB drive\u003C/li>\n\u003Cli>Select “Install Proxmox VE”\u003C/li>\n\u003Cli>Accept the EULA\u003C/li>\n\u003Cli>Select the target hard drive (this will erase all data on the drive)\u003C/li>\n\u003Cli>Configure country, time zone, and keyboard layout\u003C/li>\n\u003Cli>Set a strong root password and provide an email address\u003C/li>\n\u003Cli>Configure network settings:\n\u003Cul>\n\u003Cli>Enter a hostname (FQDN format: proxmox.yourdomain.local)\u003C/li>\n\u003Cli>IP address, netmask, gateway\u003C/li>\n\u003Cli>DNS server\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003Cli>Review the settings and confirm to start the installation\u003C/li>\n\u003Cli>Once completed, remove the USB drive and reboot\u003C/li>\n\u003C/ol>\n\u003Ch3 id=\"3-initial-configuration\">3. Initial Configuration\u003C/h3>\n\u003Cp>Access the web interface by navigating to \u003Ccode>https://<your-proxmox-ip>:8006\u003C/code> in your browser. Log in with:\u003C/p>\n\u003Cul>\n\u003Cli>Username: root\u003C/li>\n\u003Cli>Password: (the one you set during installation)\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"post-installation-tasks\">Post-Installation Tasks\u003C/h2>\n\u003Ch3 id=\"1-update-proxmox-ve\">1. Update Proxmox VE\u003C/h3>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">apt\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> update\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">apt\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> dist-upgrade\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"2-remove-subscription-notice-optional\">2. Remove Subscription Notice (Optional)\u003C/h3>\n\u003Cp>For home lab use, you can remove the subscription notice:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">echo\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">DPkg::Post-Invoke { \u003C/span>\u003Cspan style=\"color:#FF79C6\">\\\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">dpkg -V proxmox-widget-toolkit | grep -q '/proxmoxlib\\.js$'; if [ \u003C/span>\u003Cspan style=\"color:#FF79C6\">\\$\u003C/span>\u003Cspan style=\"color:#F1FA8C\">? -eq 1 ]; then { echo 'Removing subscription nag from UI...'; sed -i '/.*data\\.status.*subscription.*/d' /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js; }; fi\u003C/span>\u003Cspan style=\"color:#FF79C6\">\\\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">; };\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\"> >\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /etc/apt/apt.conf.d/no-subscription-warning\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"3-configure-storage\">3. Configure Storage\u003C/h3>\n\u003Ch4 id=\"local-storage\">Local Storage\u003C/h4>\n\u003Cp>By default, Proxmox VE creates several storage locations:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Cstrong>local\u003C/strong>: For ISO images, container templates, and snippets\u003C/li>\n\u003Cli>\u003Cstrong>local-lvm\u003C/strong>: For VM disk images\u003C/li>\n\u003C/ul>\n\u003Cp>To add a new storage, go to Datacenter > Storage > Add:\u003C/p>\n\u003Cul>\n\u003Cli>For local directories: Select “Directory”\u003C/li>\n\u003Cli>For network storage: Select “NFS” or “CIFS”\u003C/li>\n\u003Cli>For block storage: Select “LVM”, “LVM-Thin”, or “ZFS”\u003C/li>\n\u003C/ul>\n\u003Ch4 id=\"zfs-storage-pool-recommended\">ZFS Storage Pool (Recommended)\u003C/h4>\n\u003Cp>ZFS offers excellent performance and data protection:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Create a ZFS pool using available disks\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">zpool\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> create\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -f\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> rpool\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /dev/sdb\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /dev/sdc\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Add the pool to Proxmox\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">pvesm\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> add\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> zfspool\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> rpool\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -pool\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> rpool\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"4-set-up-networking\">4. Set Up Networking\u003C/h3>\n\u003Ch4 id=\"network-bridges\">Network Bridges\u003C/h4>\n\u003Cp>Proxmox VE creates a default bridge (vmbr0) during installation. To add more:\u003C/p>\n\u003Col>\n\u003Cli>Go to Node > Network > Create > Linux Bridge\u003C/li>\n\u003Cli>Configure the bridge:\n\u003Cul>\n\u003Cli>Name: vmbr1\u003C/li>\n\u003Cli>IP address/CIDR: 192.168.1.1/24 (or leave empty for unmanaged bridge)\u003C/li>\n\u003Cli>Bridge ports: (physical interface, e.g., eth1)\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003C/ol>\n\u003Ch4 id=\"vlan-configuration\">VLAN Configuration\u003C/h4>\n\u003Cp>For VLAN support:\u003C/p>\n\u003Col>\n\u003Cli>Ensure the bridge has VLAN awareness enabled\u003C/li>\n\u003Cli>In VM network settings, specify VLAN tags\u003C/li>\n\u003C/ol>\n\u003Ch2 id=\"creating-virtual-machines-and-containers\">Creating Virtual Machines and Containers\u003C/h2>\n\u003Ch3 id=\"virtual-machines-kvm\">Virtual Machines (KVM)\u003C/h3>\n\u003Col>\n\u003Cli>Go to Create VM\u003C/li>\n\u003Cli>Fill out the wizard:\n\u003Cul>\n\u003Cli>General: Name, Resource Pool\u003C/li>\n\u003Cli>OS: ISO image, type, and version\u003C/li>\n\u003Cli>System: BIOS/UEFI, Machine type\u003C/li>\n\u003Cli>Disks: Size, format, storage location\u003C/li>\n\u003Cli>CPU: Cores, type\u003C/li>\n\u003Cli>Memory: RAM size\u003C/li>\n\u003Cli>Network: Bridge, model\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003Cli>Click Finish to create the VM\u003C/li>\n\u003C/ol>\n\u003Ch3 id=\"containers-lxc\">Containers (LXC)\u003C/h3>\n\u003Col>\n\u003Cli>Go to Create CT\u003C/li>\n\u003Cli>Fill out the wizard:\n\u003Cul>\n\u003Cli>General: Hostname, Password\u003C/li>\n\u003Cli>Template: Select from available templates\u003C/li>\n\u003Cli>Disks: Size, storage location\u003C/li>\n\u003Cli>CPU: Cores\u003C/li>\n\u003Cli>Memory: RAM size\u003C/li>\n\u003Cli>Network: IP address, bridge\u003C/li>\n\u003Cli>DNS: DNS servers\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003Cli>Click Finish to create the container\u003C/li>\n\u003C/ol>\n\u003Ch2 id=\"backup-configuration\">Backup Configuration\u003C/h2>\n\u003Ch3 id=\"setting-up-backups\">Setting Up Backups\u003C/h3>\n\u003Col>\n\u003Cli>Go to Datacenter > Backup\u003C/li>\n\u003Cli>Add a new backup job:\n\u003Cul>\n\u003Cli>Select storage location\u003C/li>\n\u003Cli>Set schedule (daily, weekly, etc.)\u003C/li>\n\u003Cli>Choose VMs/containers to back up\u003C/li>\n\u003Cli>Configure compression and mode\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003C/ol>\n\u003Ch2 id=\"performance-tuning\">Performance Tuning\u003C/h2>\n\u003Ch3 id=\"cpu\">CPU\u003C/h3>\n\u003Cp>For VMs that need consistent performance:\u003C/p>\n\u003Cul>\n\u003Cli>Set CPU type to “host” for best performance\u003C/li>\n\u003Cli>Reserve CPU cores for critical VMs\u003C/li>\n\u003Cli>Use CPU pinning for high-performance workloads\u003C/li>\n\u003C/ul>\n\u003Ch3 id=\"memory\">Memory\u003C/h3>\n\u003Cul>\n\u003Cli>Enable KSM (Kernel Same-page Merging) for better memory usage\u003C/li>\n\u003Cli>Set appropriate memory ballooning for VMs\u003C/li>\n\u003C/ul>\n\u003Ch3 id=\"storage\">Storage\u003C/h3>\n\u003Cul>\n\u003Cli>Use SSDs for VM disks when possible\u003C/li>\n\u003Cli>Enable write-back caching for improved performance\u003C/li>\n\u003Cli>Consider ZFS for important data with appropriate RAM allocation\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"conclusion\">Conclusion\u003C/h2>\n\u003Cp>Proxmox VE is a powerful, flexible virtualization platform perfect for home labs. With its combination of virtual machines and containers, you can build a versatile lab environment for testing, development, and running production services.\u003C/p>\n\u003Cp>After following this guide, you should have a fully functional Proxmox VE server ready to host your virtual infrastructure. In future articles, we’ll explore advanced topics like clustering, high availability, and integration with other infrastructure tools.\u003C/p>",{"headings":84,"localImagePaths":164,"remoteImagePaths":165,"frontmatter":166,"imagePaths":169},[85,87,90,93,96,100,103,106,109,112,115,118,122,125,128,131,134,137,140,143,146,149,152,155,158,161],{"depth":52,"slug":86,"text":70},"complete-proxmox-ve-setup-guide",{"depth":55,"slug":88,"text":89},"why-choose-proxmox-ve","Why Choose Proxmox VE?",{"depth":55,"slug":91,"text":92},"hardware-requirements","Hardware Requirements",{"depth":55,"slug":94,"text":95},"installation","Installation",{"depth":97,"slug":98,"text":99},3,"1-prepare-for-installation","1. Prepare for Installation",{"depth":97,"slug":101,"text":102},"2-install-proxmox-ve","2. Install Proxmox VE",{"depth":97,"slug":104,"text":105},"3-initial-configuration","3. Initial Configuration",{"depth":55,"slug":107,"text":108},"post-installation-tasks","Post-Installation Tasks",{"depth":97,"slug":110,"text":111},"1-update-proxmox-ve","1. Update Proxmox VE",{"depth":97,"slug":113,"text":114},"2-remove-subscription-notice-optional","2. Remove Subscription Notice (Optional)",{"depth":97,"slug":116,"text":117},"3-configure-storage","3. Configure Storage",{"depth":119,"slug":120,"text":121},4,"local-storage","Local Storage",{"depth":119,"slug":123,"text":124},"zfs-storage-pool-recommended","ZFS Storage Pool (Recommended)",{"depth":97,"slug":126,"text":127},"4-set-up-networking","4. Set Up Networking",{"depth":119,"slug":129,"text":130},"network-bridges","Network Bridges",{"depth":119,"slug":132,"text":133},"vlan-configuration","VLAN Configuration",{"depth":55,"slug":135,"text":136},"creating-virtual-machines-and-containers","Creating Virtual Machines and Containers",{"depth":97,"slug":138,"text":139},"virtual-machines-kvm","Virtual Machines (KVM)",{"depth":97,"slug":141,"text":142},"containers-lxc","Containers (LXC)",{"depth":55,"slug":144,"text":145},"backup-configuration","Backup Configuration",{"depth":97,"slug":147,"text":148},"setting-up-backups","Setting Up Backups",{"depth":55,"slug":150,"text":151},"performance-tuning","Performance Tuning",{"depth":97,"slug":153,"text":154},"cpu","CPU",{"depth":97,"slug":156,"text":157},"memory","Memory",{"depth":97,"slug":159,"text":160},"storage","Storage",{"depth":55,"slug":162,"text":163},"conclusion","Conclusion",[],[],{"title":70,"description":71,"pubDate":167,"heroImage":17,"category":73,"tags":168,"readTime":77},["Date","2025-04-19T00:00:00.000Z"],[75,76,22,73],[],"proxmox-setup-guide.md","k3s-cluster",{"id":171,"data":173,"body":183,"filePath":184,"digest":185,"rendered":186,"legacyId":215},{"title":174,"description":175,"pubDate":176,"heroImage":177,"category":178,"tags":179,"draft":182},"Setting Up a K3s Kubernetes Cluster","A comprehensive guide to setting up a K3s cluster for your home lab or edge environment, with high availability and persistent storage.","2023-11-15","/blog/images/posts/k3installation.png","Kubernetes",[180,181,22,73],"kubernetes","k3s",false,"# Setting Up a K3s Kubernetes Cluster\n\nK3s is a lightweight, certified Kubernetes distribution designed for resource-constrained environments like edge devices, IoT, and home labs. This guide will walk you through setting up a production-ready K3s cluster.\n\n## Prerequisites\n\n- At least two machines (physical or virtual) for high availability\n- Ubuntu 20.04 LTS or newer\n- At least 2GB RAM per node\n- 20GB+ storage per node\n- Network connectivity between all nodes\n\n## Installing the Server Node\n\nFirst, let's install the primary server node:\n\n```bash\ncurl -sfL https://get.k3s.io | sh -s - server \\\n --cluster-init \\\n --tls-san=server-ip-or-hostname \\\n --disable traefik \\\n --disable servicelb\n```\n\nThis initializes the cluster with:\n- HA enabled with `--cluster-init`\n- Custom TLS SAN for API server\n- Disabled default traefik ingress (we'll use Nginx)\n- Disabled default ServiceLB (we'll use MetalLB)\n\n## Installing Agent Nodes\n\nOn each worker node, run:\n\n```bash\ncurl -sfL https://get.k3s.io | K3S_URL=https://server-ip:6443 K3S_TOKEN=node-token sh -\n```\n\nReplace `server-ip` with your server's IP and get the token from `/var/lib/rancher/k3s/server/node-token` on the server.\n\n## Adding High Availability\n\nFor HA, add additional server nodes:\n\n```bash\ncurl -sfL https://get.k3s.io | sh -s - server \\\n --server https://first-server-ip:6443 \\\n --token node-token \\\n --tls-san=this-server-ip \\\n --disable traefik \\\n --disable servicelb\n```\n\n## Setting Up Persistent Storage\n\nWe'll use Longhorn for distributed storage:\n\n```bash\nkubectl apply -f https://raw.githubusercontent.com/longhorn/longhorn/master/deploy/longhorn.yaml\n```\n\nLonghorn provides replicated block storage across your nodes for high availability.\n\n## Next Steps\n\nAfter setting up your cluster, you might want to:\n\n1. Install a proper ingress controller (Nginx, Traefik)\n2. Set up a load balancer (MetalLB)\n3. Configure monitoring with Prometheus and Grafana\n4. Implement GitOps with Flux or ArgoCD\n\nStay tuned for detailed guides on each of these topics!\n\n---\n\nThis guide provides a starting point for your journey with K3s Kubernetes. In future posts, we'll dive deeper into advanced configurations.","src/content/blog/k3s-cluster.md","898fbedcd3e14a90",{"html":187,"metadata":188},"\u003Ch1 id=\"setting-up-a-k3s-kubernetes-cluster\">Setting Up a K3s Kubernetes Cluster\u003C/h1>\n\u003Cp>K3s is a lightweight, certified Kubernetes distribution designed for resource-constrained environments like edge devices, IoT, and home labs. This guide will walk you through setting up a production-ready K3s cluster.\u003C/p>\n\u003Ch2 id=\"prerequisites\">Prerequisites\u003C/h2>\n\u003Cul>\n\u003Cli>At least two machines (physical or virtual) for high availability\u003C/li>\n\u003Cli>Ubuntu 20.04 LTS or newer\u003C/li>\n\u003Cli>At least 2GB RAM per node\u003C/li>\n\u003Cli>20GB+ storage per node\u003C/li>\n\u003Cli>Network connectivity between all nodes\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"installing-the-server-node\">Installing the Server Node\u003C/h2>\n\u003Cp>First, let’s install the primary server node:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">curl\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -sfL\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> https://get.k3s.io\u003C/span>\u003Cspan style=\"color:#FF79C6\"> |\u003C/span>\u003Cspan style=\"color:#50FA7B\"> sh\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -s\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> server\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> --cluster-init\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> --tls-san=server-ip-or-hostname\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> --disable\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> traefik\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> --disable\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> servicelb\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>This initializes the cluster with:\u003C/p>\n\u003Cul>\n\u003Cli>HA enabled with \u003Ccode>--cluster-init\u003C/code>\u003C/li>\n\u003Cli>Custom TLS SAN for API server\u003C/li>\n\u003Cli>Disabled default traefik ingress (we’ll use Nginx)\u003C/li>\n\u003Cli>Disabled default ServiceLB (we’ll use MetalLB)\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"installing-agent-nodes\">Installing Agent Nodes\u003C/h2>\n\u003Cp>On each worker node, run:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">curl\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -sfL\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> https://get.k3s.io\u003C/span>\u003Cspan style=\"color:#FF79C6\"> |\u003C/span>\u003Cspan style=\"color:#BD93F9\"> K3S_URL\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#F1FA8C\">https://server-ip:6443\u003C/span>\u003Cspan style=\"color:#BD93F9\"> K3S_TOKEN\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#F1FA8C\">node-token\u003C/span>\u003Cspan style=\"color:#50FA7B\"> sh\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> -\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Replace \u003Ccode>server-ip\u003C/code> with your server’s IP and get the token from \u003Ccode>/var/lib/rancher/k3s/server/node-token\u003C/code> on the server.\u003C/p>\n\u003Ch2 id=\"adding-high-availability\">Adding High Availability\u003C/h2>\n\u003Cp>For HA, add additional server nodes:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">curl\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -sfL\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> https://get.k3s.io\u003C/span>\u003Cspan style=\"color:#FF79C6\"> |\u003C/span>\u003Cspan style=\"color:#50FA7B\"> sh\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -s\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> server\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> --server\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> https://first-server-ip:6443\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> --token\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> node-token\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> --tls-san=this-server-ip\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> --disable\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> traefik\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> --disable\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> servicelb\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"setting-up-persistent-storage\">Setting Up Persistent Storage\u003C/h2>\n\u003Cp>We’ll use Longhorn for distributed storage:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">kubectl\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> apply\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -f\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> https://raw.githubusercontent.com/longhorn/longhorn/master/deploy/longhorn.yaml\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Longhorn provides replicated block storage across your nodes for high availability.\u003C/p>\n\u003Ch2 id=\"next-steps\">Next Steps\u003C/h2>\n\u003Cp>After setting up your cluster, you might want to:\u003C/p>\n\u003Col>\n\u003Cli>Install a proper ingress controller (Nginx, Traefik)\u003C/li>\n\u003Cli>Set up a load balancer (MetalLB)\u003C/li>\n\u003Cli>Configure monitoring with Prometheus and Grafana\u003C/li>\n\u003Cli>Implement GitOps with Flux or ArgoCD\u003C/li>\n\u003C/ol>\n\u003Cp>Stay tuned for detailed guides on each of these topics!\u003C/p>\n\u003Chr>\n\u003Cp>This guide provides a starting point for your journey with K3s Kubernetes. In future posts, we’ll dive deeper into advanced configurations.\u003C/p>",{"headings":189,"localImagePaths":210,"remoteImagePaths":211,"frontmatter":212,"imagePaths":214},[190,192,195,198,201,204,207],{"depth":52,"slug":191,"text":174},"setting-up-a-k3s-kubernetes-cluster",{"depth":55,"slug":193,"text":194},"prerequisites","Prerequisites",{"depth":55,"slug":196,"text":197},"installing-the-server-node","Installing the Server Node",{"depth":55,"slug":199,"text":200},"installing-agent-nodes","Installing Agent Nodes",{"depth":55,"slug":202,"text":203},"adding-high-availability","Adding High Availability",{"depth":55,"slug":205,"text":206},"setting-up-persistent-storage","Setting Up Persistent Storage",{"depth":55,"slug":208,"text":209},"next-steps","Next Steps",[],[],{"title":174,"description":175,"pubDate":176,"heroImage":177,"category":178,"tags":213,"draft":182},[180,181,22,73],[],"k3s-cluster.md","k3s-installation-guide",{"id":216,"data":218,"body":225,"filePath":226,"digest":227,"rendered":228,"legacyId":259},{"title":219,"description":220,"pubDate":221,"heroImage":177,"category":180,"tags":222,"readTime":224},"K3s Installation Guide","A comprehensive guide to installing and configuring K3s for your home lab",["Date","2025-04-19T00:00:00.000Z"],[180,181,22,223],"tutorial","8 min read","# K3s Installation Guide\n\nK3s is a lightweight Kubernetes distribution designed for resource-constrained environments, perfect for home labs and edge computing. This guide will walk you through the installation process from start to finish.\n\n## Prerequisites\n\n- A machine running Linux (Ubuntu 20.04+ recommended)\n- Minimum 1GB RAM (2GB+ recommended for multi-workload clusters)\n- 20GB+ of disk space\n- Root access or sudo privileges\n\n## Basic Installation\n\nThe simplest way to install K3s is using the installation script:\n\n```bash\ncurl -sfL https://get.k3s.io | sh -\n```\n\nThis will install K3s as a server and start the service. To verify it's running:\n\n```bash\nsudo k3s kubectl get node\n```\n\n## Advanced Installation Options\n\n### Master Node with Custom Options\n\nFor more control, you can use environment variables:\n\n```bash\ncurl -sfL https://get.k3s.io | INSTALL_K3S_EXEC=\"--disable=traefik\" sh -\n```\n\n### Adding Worker Nodes\n\n1. On your master node, get the node token:\n\n```bash\nsudo cat /var/lib/rancher/k3s/server/node-token\n```\n\n2. On each worker node, run:\n\n```bash\ncurl -sfL https://get.k3s.io | K3S_URL=https://\u003Cmaster-node-ip>:6443 K3S_TOKEN=\u003Cnode-token> sh -\n```\n\n## Accessing the Cluster\n\nAfter installation, the kubeconfig file is written to `/etc/rancher/k3s/k3s.yaml`. To use kubectl externally:\n\n1. Copy this file to your local machine\n2. Set the KUBECONFIG environment variable:\n\n```bash\nexport KUBECONFIG=/path/to/k3s.yaml\n```\n\n## Uninstalling K3s\n\nIf you need to uninstall:\n\n- On server nodes: `/usr/local/bin/k3s-uninstall.sh`\n- On agent nodes: `/usr/local/bin/k3s-agent-uninstall.sh`\n\n## Next Steps\n\nNow that you have K3s running, you might want to:\n\n- Deploy your first application\n- Set up persistent storage\n- Configure ingress for external access\n\nStay tuned for more guides on these topics!","src/content/blog/k3s-installation-guide.md","a06a029a2004bf34",{"html":229,"metadata":230},"\u003Ch1 id=\"k3s-installation-guide\">K3s Installation Guide\u003C/h1>\n\u003Cp>K3s is a lightweight Kubernetes distribution designed for resource-constrained environments, perfect for home labs and edge computing. This guide will walk you through the installation process from start to finish.\u003C/p>\n\u003Ch2 id=\"prerequisites\">Prerequisites\u003C/h2>\n\u003Cul>\n\u003Cli>A machine running Linux (Ubuntu 20.04+ recommended)\u003C/li>\n\u003Cli>Minimum 1GB RAM (2GB+ recommended for multi-workload clusters)\u003C/li>\n\u003Cli>20GB+ of disk space\u003C/li>\n\u003Cli>Root access or sudo privileges\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"basic-installation\">Basic Installation\u003C/h2>\n\u003Cp>The simplest way to install K3s is using the installation script:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">curl\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -sfL\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> https://get.k3s.io\u003C/span>\u003Cspan style=\"color:#FF79C6\"> |\u003C/span>\u003Cspan style=\"color:#50FA7B\"> sh\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> -\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>This will install K3s as a server and start the service. To verify it’s running:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">sudo\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> k3s\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> kubectl\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> get\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> node\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"advanced-installation-options\">Advanced Installation Options\u003C/h2>\n\u003Ch3 id=\"master-node-with-custom-options\">Master Node with Custom Options\u003C/h3>\n\u003Cp>For more control, you can use environment variables:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">curl\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -sfL\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> https://get.k3s.io\u003C/span>\u003Cspan style=\"color:#FF79C6\"> |\u003C/span>\u003Cspan style=\"color:#BD93F9\"> INSTALL_K3S_EXEC\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">--disable=traefik\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#50FA7B\"> sh\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> -\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"adding-worker-nodes\">Adding Worker Nodes\u003C/h3>\n\u003Col>\n\u003Cli>On your master node, get the node token:\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">sudo\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> cat\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /var/lib/rancher/k3s/server/node-token\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Col start=\"2\">\n\u003Cli>On each worker node, run:\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">curl\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -sfL\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> https://get.k3s.io\u003C/span>\u003Cspan style=\"color:#FF79C6\"> |\u003C/span>\u003Cspan style=\"color:#BD93F9\"> K3S_URL\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#F1FA8C\">https://\u003C/span>\u003Cspan style=\"color:#FF79C6\"><\u003C/span>\u003Cspan style=\"color:#F1FA8C\">master-node-ip\u003C/span>\u003Cspan style=\"color:#FF79C6\">>\u003C/span>\u003Cspan style=\"color:#F1FA8C\">:6443\u003C/span>\u003Cspan style=\"color:#BD93F9\"> K3S_TOKEN\u003C/span>\u003Cspan style=\"color:#FF79C6\">=<\u003C/span>\u003Cspan style=\"color:#F1FA8C\">node-token\u003C/span>\u003Cspan style=\"color:#FF79C6\">>\u003C/span>\u003Cspan style=\"color:#50FA7B\"> sh\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> -\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"accessing-the-cluster\">Accessing the Cluster\u003C/h2>\n\u003Cp>After installation, the kubeconfig file is written to \u003Ccode>/etc/rancher/k3s/k3s.yaml\u003C/code>. To use kubectl externally:\u003C/p>\n\u003Col>\n\u003Cli>Copy this file to your local machine\u003C/li>\n\u003Cli>Set the KUBECONFIG environment variable:\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\">export\u003C/span>\u003Cspan style=\"color:#BD93F9\"> KUBECONFIG\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#F8F8F2\">/\u003C/span>\u003Cspan style=\"color:#BD93F9\">path\u003C/span>\u003Cspan style=\"color:#F8F8F2\">/\u003C/span>\u003Cspan style=\"color:#BD93F9\">to\u003C/span>\u003Cspan style=\"color:#F8F8F2\">/\u003C/span>\u003Cspan style=\"color:#BD93F9\">k3s\u003C/span>\u003Cspan style=\"color:#F8F8F2\">.\u003C/span>\u003Cspan style=\"color:#BD93F9\">yaml\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"uninstalling-k3s\">Uninstalling K3s\u003C/h2>\n\u003Cp>If you need to uninstall:\u003C/p>\n\u003Cul>\n\u003Cli>On server nodes: \u003Ccode>/usr/local/bin/k3s-uninstall.sh\u003C/code>\u003C/li>\n\u003Cli>On agent nodes: \u003Ccode>/usr/local/bin/k3s-agent-uninstall.sh\u003C/code>\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"next-steps\">Next Steps\u003C/h2>\n\u003Cp>Now that you have K3s running, you might want to:\u003C/p>\n\u003Cul>\n\u003Cli>Deploy your first application\u003C/li>\n\u003Cli>Set up persistent storage\u003C/li>\n\u003Cli>Configure ingress for external access\u003C/li>\n\u003C/ul>\n\u003Cp>Stay tuned for more guides on these topics!\u003C/p>",{"headings":231,"localImagePaths":253,"remoteImagePaths":254,"frontmatter":255,"imagePaths":258},[232,233,234,237,240,243,246,249,252],{"depth":52,"slug":216,"text":219},{"depth":55,"slug":193,"text":194},{"depth":55,"slug":235,"text":236},"basic-installation","Basic Installation",{"depth":55,"slug":238,"text":239},"advanced-installation-options","Advanced Installation Options",{"depth":97,"slug":241,"text":242},"master-node-with-custom-options","Master Node with Custom Options",{"depth":97,"slug":244,"text":245},"adding-worker-nodes","Adding Worker Nodes",{"depth":55,"slug":247,"text":248},"accessing-the-cluster","Accessing the Cluster",{"depth":55,"slug":250,"text":251},"uninstalling-k3s","Uninstalling K3s",{"depth":55,"slug":208,"text":209},[],[],{"title":219,"description":220,"pubDate":256,"heroImage":177,"category":180,"tags":257,"readTime":224},["Date","2025-04-19T00:00:00.000Z"],[180,181,22,223],[],"k3s-installation-guide.md","gitops-with-flux-cd",{"id":260,"data":262,"body":273,"filePath":274,"digest":275,"rendered":276,"legacyId":311},{"title":263,"description":264,"pubDate":265,"heroImage":17,"category":266,"tags":267,"readTime":272},"GitOps with Flux CD","Implementing GitOps workflows on Kubernetes using Flux CD",["Date","2025-04-19T00:00:00.000Z"],"devops",[180,268,269,270,271],"gitops","flux","ci-cd","automation","10 min read","# GitOps with Flux CD\n\nGitOps is revolutionizing the way teams deploy and manage applications on Kubernetes. This guide will walk you through implementing a GitOps workflow using Flux CD, an open-source continuous delivery tool.\n\n## What is GitOps?\n\nGitOps is an operational framework that takes DevOps best practices used for application development such as version control, collaboration, compliance, and CI/CD, and applies them to infrastructure automation.\n\nWith GitOps:\n- Git is the single source of truth for the desired state of your infrastructure\n- Changes to the desired state are declarative and version controlled\n- Approved changes are automatically applied to your infrastructure\n\n## Why Flux CD?\n\nFlux CD is a GitOps tool that ensures that your Kubernetes cluster matches the desired state specified in a Git repository. Key features include:\n\n- Automated sync between your Git repository and cluster state\n- Support for Kustomize, Helm, and plain Kubernetes manifests\n- Multi-tenancy via RBAC\n- Strong security practices, including image verification\n\n## Installation\n\n### Prerequisites\n\n- A Kubernetes cluster (K3s, Kind, or any other distribution)\n- kubectl configured to access your cluster\n- A GitHub (or GitLab/Bitbucket) account and repository\n\n### Installing Flux\n\n1. Install the Flux CLI:\n\n```bash\ncurl -s https://fluxcd.io/install.sh | sudo bash\n```\n\n2. Export your GitHub personal access token:\n\n```bash\nexport GITHUB_TOKEN=\u003Cyour-token>\n```\n\n3. Bootstrap Flux:\n\n```bash\nflux bootstrap github \\\n --owner=\u003Cyour-github-username> \\\n --repository=\u003Crepository-name> \\\n --path=clusters/my-cluster \\\n --personal\n```\n\n## Setting Up Your First Application\n\n1. Create a basic directory structure in your Git repository:\n\n```\n└── clusters/\n └── my-cluster/\n ├── flux-system/ # Created by bootstrap\n └── apps/\n └── podinfo/\n ├── namespace.yaml\n ├── deployment.yaml\n └── service.yaml\n```\n\n2. Create a Flux Kustomization to deploy your app:\n\n```yaml\napiVersion: kustomize.toolkit.fluxcd.io/v1beta2\nkind: Kustomization\nmetadata:\n name: podinfo\n namespace: flux-system\nspec:\n interval: 5m0s\n path: ./clusters/my-cluster/apps/podinfo\n prune: true\n sourceRef:\n kind: GitRepository\n name: flux-system\n```\n\n3. Commit and push your changes, and Flux will automatically deploy your application!\n\n## Advanced Features\n\n### Automated Image Updates\n\nFlux can automatically update your deployments when new images are available:\n\n```yaml\napiVersion: image.toolkit.fluxcd.io/v1beta1\nkind: ImageRepository\nmetadata:\n name: podinfo\n namespace: flux-system\nspec:\n image: ghcr.io/stefanprodan/podinfo\n interval: 1m0s\n---\napiVersion: image.toolkit.fluxcd.io/v1beta1\nkind: ImagePolicy\nmetadata:\n name: podinfo\n namespace: flux-system\nspec:\n imageRepositoryRef:\n name: podinfo\n policy:\n semver:\n range: 6.x.x\n```\n\n### Working with Helm Charts\n\nFlux makes it easy to manage Helm releases:\n\n```yaml\napiVersion: source.toolkit.fluxcd.io/v1beta2\nkind: HelmRepository\nmetadata:\n name: bitnami\n namespace: flux-system\nspec:\n interval: 30m\n url: https://charts.bitnami.com/bitnami\n---\napiVersion: helm.toolkit.fluxcd.io/v2beta1\nkind: HelmRelease\nmetadata:\n name: redis\n namespace: flux-system\nspec:\n interval: 5m\n chart:\n spec:\n chart: redis\n version: \"16.x\"\n sourceRef:\n kind: HelmRepository\n name: bitnami\n values:\n architecture: standalone\n```\n\n## Conclusion\n\nFlux CD provides a powerful, secure, and flexible platform for implementing GitOps workflows. By following this guide, you'll be well on your way to managing your Kubernetes infrastructure using GitOps principles.\n\nStay tuned for more advanced GitOps patterns and best practices!","src/content/blog/gitops-with-flux-cd.md","da96212cbf585d51",{"html":277,"metadata":278},"\u003Ch1 id=\"gitops-with-flux-cd\">GitOps with Flux CD\u003C/h1>\n\u003Cp>GitOps is revolutionizing the way teams deploy and manage applications on Kubernetes. This guide will walk you through implementing a GitOps workflow using Flux CD, an open-source continuous delivery tool.\u003C/p>\n\u003Ch2 id=\"what-is-gitops\">What is GitOps?\u003C/h2>\n\u003Cp>GitOps is an operational framework that takes DevOps best practices used for application development such as version control, collaboration, compliance, and CI/CD, and applies them to infrastructure automation.\u003C/p>\n\u003Cp>With GitOps:\u003C/p>\n\u003Cul>\n\u003Cli>Git is the single source of truth for the desired state of your infrastructure\u003C/li>\n\u003Cli>Changes to the desired state are declarative and version controlled\u003C/li>\n\u003Cli>Approved changes are automatically applied to your infrastructure\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"why-flux-cd\">Why Flux CD?\u003C/h2>\n\u003Cp>Flux CD is a GitOps tool that ensures that your Kubernetes cluster matches the desired state specified in a Git repository. Key features include:\u003C/p>\n\u003Cul>\n\u003Cli>Automated sync between your Git repository and cluster state\u003C/li>\n\u003Cli>Support for Kustomize, Helm, and plain Kubernetes manifests\u003C/li>\n\u003Cli>Multi-tenancy via RBAC\u003C/li>\n\u003Cli>Strong security practices, including image verification\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"installation\">Installation\u003C/h2>\n\u003Ch3 id=\"prerequisites\">Prerequisites\u003C/h3>\n\u003Cul>\n\u003Cli>A Kubernetes cluster (K3s, Kind, or any other distribution)\u003C/li>\n\u003Cli>kubectl configured to access your cluster\u003C/li>\n\u003Cli>A GitHub (or GitLab/Bitbucket) account and repository\u003C/li>\n\u003C/ul>\n\u003Ch3 id=\"installing-flux\">Installing Flux\u003C/h3>\n\u003Col>\n\u003Cli>Install the Flux CLI:\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">curl\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -s\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> https://fluxcd.io/install.sh\u003C/span>\u003Cspan style=\"color:#FF79C6\"> |\u003C/span>\u003Cspan style=\"color:#50FA7B\"> sudo\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> bash\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Col start=\"2\">\n\u003Cli>Export your GitHub personal access token:\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\">export\u003C/span>\u003Cspan style=\"color:#BD93F9\"> GITHUB_TOKEN\u003C/span>\u003Cspan style=\"color:#FF79C6\">=<\u003C/span>\u003Cspan style=\"color:#BD93F9\">your-token\u003C/span>\u003Cspan style=\"color:#FF79C6\">>\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Col start=\"3\">\n\u003Cli>Bootstrap Flux:\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">flux\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> bootstrap\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> github\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> --owner=\u003C/span>\u003Cspan style=\"color:#FF79C6\"><\u003C/span>\u003Cspan style=\"color:#BD93F9\">your-github-username\u003C/span>\u003Cspan style=\"color:#FF79C6\">>\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> --repository=\u003C/span>\u003Cspan style=\"color:#FF79C6\"><\u003C/span>\u003Cspan style=\"color:#BD93F9\">repository-name\u003C/span>\u003Cspan style=\"color:#FF79C6\">>\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> --path=clusters/my-cluster\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> --personal\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"setting-up-your-first-application\">Setting Up Your First Application\u003C/h2>\n\u003Col>\n\u003Cli>Create a basic directory structure in your Git repository:\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"plaintext\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan>└── clusters/\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> └── my-cluster/\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> ├── flux-system/ # Created by bootstrap\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> └── apps/\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> └── podinfo/\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> ├── namespace.yaml\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> ├── deployment.yaml\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> └── service.yaml\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Col start=\"2\">\n\u003Cli>Create a Flux Kustomization to deploy your app:\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">apiVersion\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> kustomize.toolkit.fluxcd.io/v1beta2\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">kind\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Kustomization\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">metadata\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> podinfo\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> namespace\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> flux-system\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> interval\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 5m0s\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> path\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ./clusters/my-cluster/apps/podinfo\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> prune\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> true\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> sourceRef\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> kind\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> GitRepository\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> flux-system\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Col start=\"3\">\n\u003Cli>Commit and push your changes, and Flux will automatically deploy your application!\u003C/li>\n\u003C/ol>\n\u003Ch2 id=\"advanced-features\">Advanced Features\u003C/h2>\n\u003Ch3 id=\"automated-image-updates\">Automated Image Updates\u003C/h3>\n\u003Cp>Flux can automatically update your deployments when new images are available:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">apiVersion\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> image.toolkit.fluxcd.io/v1beta1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">kind\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ImageRepository\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">metadata\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> podinfo\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> namespace\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> flux-system\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> image\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ghcr.io/stefanprodan/podinfo\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> interval\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 1m0s\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">---\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">apiVersion\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> image.toolkit.fluxcd.io/v1beta1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">kind\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ImagePolicy\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">metadata\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> podinfo\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> namespace\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> flux-system\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> imageRepositoryRef\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> podinfo\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> policy\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> semver\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> range\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 6.x.x\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"working-with-helm-charts\">Working with Helm Charts\u003C/h3>\n\u003Cp>Flux makes it easy to manage Helm releases:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">apiVersion\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> source.toolkit.fluxcd.io/v1beta2\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">kind\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> HelmRepository\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">metadata\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> bitnami\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> namespace\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> flux-system\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> interval\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 30m\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> url\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> https://charts.bitnami.com/bitnami\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">---\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">apiVersion\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> helm.toolkit.fluxcd.io/v2beta1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">kind\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> HelmRelease\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">metadata\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> redis\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> namespace\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> flux-system\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> interval\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 5m\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> chart\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> chart\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> redis\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> version\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">16.x\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> sourceRef\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> kind\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> HelmRepository\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> bitnami\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> values\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> architecture\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> standalone\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"conclusion\">Conclusion\u003C/h2>\n\u003Cp>Flux CD provides a powerful, secure, and flexible platform for implementing GitOps workflows. By following this guide, you’ll be well on your way to managing your Kubernetes infrastructure using GitOps principles.\u003C/p>\n\u003Cp>Stay tuned for more advanced GitOps patterns and best practices!\u003C/p>",{"headings":279,"localImagePaths":305,"remoteImagePaths":306,"frontmatter":307,"imagePaths":310},[280,281,284,287,288,289,292,295,298,301,304],{"depth":52,"slug":260,"text":263},{"depth":55,"slug":282,"text":283},"what-is-gitops","What is GitOps?",{"depth":55,"slug":285,"text":286},"why-flux-cd","Why Flux CD?",{"depth":55,"slug":94,"text":95},{"depth":97,"slug":193,"text":194},{"depth":97,"slug":290,"text":291},"installing-flux","Installing Flux",{"depth":55,"slug":293,"text":294},"setting-up-your-first-application","Setting Up Your First Application",{"depth":55,"slug":296,"text":297},"advanced-features","Advanced Features",{"depth":97,"slug":299,"text":300},"automated-image-updates","Automated Image Updates",{"depth":97,"slug":302,"text":303},"working-with-helm-charts","Working with Helm Charts",{"depth":55,"slug":162,"text":163},[],[],{"title":263,"description":264,"pubDate":308,"heroImage":17,"category":266,"tags":309,"readTime":272},["Date","2025-04-19T00:00:00.000Z"],[180,268,269,270,271],[],"gitops-with-flux-cd.md","prometheus-monitoring",{"id":312,"data":314,"body":325,"filePath":326,"digest":327,"rendered":328,"legacyId":378},{"title":315,"description":316,"pubDate":317,"heroImage":318,"category":319,"tags":320,"draft":182},"Monitoring Your Kubernetes Cluster with Prometheus and Grafana","A comprehensive guide to setting up a robust monitoring solution for your Kubernetes cluster using Prometheus and Grafana.","2023-09-25","/blog/images/posts/prometheus-dashboard.svg","Monitoring",[180,321,322,323,324],"prometheus","grafana","monitoring","observability","# Monitoring Your Kubernetes Cluster with Prometheus and Grafana\n\nIn today's complex Kubernetes environments, having a robust monitoring solution is not just nice to have—it's essential. This guide will walk you through setting up Prometheus and Grafana to monitor your K3s or any other Kubernetes cluster.\n\n## Why Prometheus and Grafana?\n\n- **Prometheus**: An open-source systems monitoring and alerting toolkit that collects and stores metrics as time series data\n- **Grafana**: A multi-platform open-source analytics and interactive visualization web application that provides charts, graphs, and alerts when connected to supported data sources\n\nTogether, they form a powerful monitoring stack that provides insights into your cluster's health and performance.\n\n## Prerequisites\n\nBefore we begin, ensure you have:\n\n- A running Kubernetes cluster (this guide uses K3s)\n- `kubectl` configured to communicate with your cluster\n- Helm 3 installed\n\n## Installation using Helm\n\nThe easiest way to install Prometheus and Grafana is using the kube-prometheus-stack Helm chart, which includes:\n\n- Prometheus Operator\n- Prometheus instance\n- Alertmanager\n- Grafana\n- Node Exporter\n- Kube State Metrics\n\nLet's create a namespace and install the stack:\n\n```bash\n# Create a dedicated namespace\nkubectl create namespace monitoring\n\n# Add the Prometheus community Helm repository\nhelm repo add prometheus-community https://prometheus-community.github.io/helm-charts\nhelm repo update\n\n# Install the kube-prometheus-stack\nhelm install prometheus prometheus-community/kube-prometheus-stack \\\n --namespace monitoring \\\n --set grafana.adminPassword=your-strong-password\n```\n\nReplace `your-strong-password` with a secure password for the Grafana admin user.\n\n## Accessing the Dashboards\n\nBy default, the services are not exposed outside the cluster. To access them, you can use port-forwarding:\n\n### Grafana\n\n```bash\nkubectl port-forward -n monitoring svc/prometheus-grafana 3000:80\n```\n\nThen access Grafana at http://localhost:3000 with username `admin` and the password you specified during installation.\n\n### Prometheus\n\n```bash\nkubectl port-forward -n monitoring svc/prometheus-operated 9090:9090\n```\n\nAccess the Prometheus UI at http://localhost:9090.\n\n## Setting Up Ingress (Optional)\n\nFor production environments, you'll want to set up proper ingress. Here's an example using Nginx ingress:\n\n```yaml\napiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n name: grafana-ingress\n namespace: monitoring\n annotations:\n kubernetes.io/ingress.class: nginx\n nginx.ingress.kubernetes.io/ssl-redirect: \"true\"\nspec:\n rules:\n - host: grafana.example.com\n http:\n paths:\n - path: /\n pathType: Prefix\n backend:\n service:\n name: prometheus-grafana\n port:\n number: 80\n tls:\n - hosts:\n - grafana.example.com\n secretName: grafana-tls\n```\n\nApply this with `kubectl apply -f ingress.yaml` after replacing `grafana.example.com` with your domain.\n\n## Important Dashboards for Kubernetes\n\nGrafana comes with several pre-installed dashboards, but here are some essential ones you should import:\n\n1. **Kubernetes Cluster Overview** (ID: 10856)\n2. **Node Exporter Full** (ID: 1860)\n3. **Kubernetes Resource Requests** (ID: 13770)\n\nTo import a dashboard:\n\n1. Go to Grafana UI\n2. Click on \"+\" icon in the sidebar\n3. Select \"Import\"\n4. Enter the dashboard ID\n5. Click \"Load\"\n6. Select the Prometheus data source\n7. Click \"Import\"\n\n## Setting Up Alerts\n\nLet's set up a basic alert for node CPU usage:\n\n1. In Grafana, go to Alerting > Alert Rules\n2. Click \"New Alert Rule\"\n3. Configure the query: `instance:node_cpu_utilisation:rate5m > 0.8`\n4. Set the condition to: `IS ABOVE 0.8`\n5. Set evaluation interval: `1m`\n6. Set \"For\": `5m` (alert will fire if condition is true for 5 minutes)\n7. Add labels and annotations as needed\n8. Save the rule\n\n## Best Practices\n\n1. **Resource Limits**: Set appropriate resource requests and limits for Prometheus and Grafana\n2. **Retention Period**: Configure the retention period based on your storage capacity\n3. **Persistent Storage**: Use persistent volumes for Prometheus data\n4. **Federation**: For large clusters, consider Prometheus federation\n5. **Custom Metrics**: Set up custom metrics for your applications using client libraries\n\n## Advanced Configuration\n\nFor a production environment, you'll want to customize the Helm values. Create a `values.yaml` file:\n\n```yaml\nprometheus:\n prometheusSpec:\n retention: 15d\n resources:\n requests:\n memory: 2Gi\n cpu: 500m\n limits:\n memory: 4Gi\n cpu: 1000m\n storageSpec:\n volumeClaimTemplate:\n spec:\n storageClassName: standard\n accessModes: [\"ReadWriteOnce\"]\n resources:\n requests:\n storage: 50Gi\n\ngrafana:\n persistence:\n enabled: true\n size: 10Gi\n resources:\n requests:\n memory: 256Mi\n cpu: 100m\n limits:\n memory: 512Mi\n cpu: 200m\n```\n\nThen update your Helm release:\n\n```bash\nhelm upgrade prometheus prometheus-community/kube-prometheus-stack \\\n --namespace monitoring \\\n -f values.yaml\n```\n\n## Troubleshooting\n\n### Common Issues\n\n1. **Insufficient Resources**: If pods are crashing, check if they have enough resources allocated\n2. **Connectivity Issues**: Ensure services can communicate with each other\n3. **Data Retention**: If Prometheus is losing data, check the storage configuration\n4. **Target Scraping**: If metrics aren't appearing, check Prometheus targets status\n\n### Useful Commands\n\n```bash\n# Check pod status\nkubectl get pods -n monitoring\n\n# Check Prometheus targets\nkubectl port-forward -n monitoring svc/prometheus-operated 9090:9090\n# Then visit http://localhost:9090/targets\n\n# View Prometheus logs\nkubectl logs -n monitoring deploy/prometheus-operator\n\n# View Grafana logs\nkubectl logs -n monitoring deploy/prometheus-grafana\n```\n\n## Conclusion\n\nYou now have a robust monitoring solution for your Kubernetes cluster. With Prometheus collecting metrics and Grafana visualizing them, you'll have deep insights into your cluster's performance and health.\n\nIn future articles, we'll explore more advanced topics like custom exporters, alert integrations, and high availability setups for your monitoring stack.","src/content/blog/prometheus-monitoring.md","cb49bfb5a9a5d47a",{"html":329,"metadata":330},"\u003Ch1 id=\"monitoring-your-kubernetes-cluster-with-prometheus-and-grafana\">Monitoring Your Kubernetes Cluster with Prometheus and Grafana\u003C/h1>\n\u003Cp>In today’s complex Kubernetes environments, having a robust monitoring solution is not just nice to have—it’s essential. This guide will walk you through setting up Prometheus and Grafana to monitor your K3s or any other Kubernetes cluster.\u003C/p>\n\u003Ch2 id=\"why-prometheus-and-grafana\">Why Prometheus and Grafana?\u003C/h2>\n\u003Cul>\n\u003Cli>\u003Cstrong>Prometheus\u003C/strong>: An open-source systems monitoring and alerting toolkit that collects and stores metrics as time series data\u003C/li>\n\u003Cli>\u003Cstrong>Grafana\u003C/strong>: A multi-platform open-source analytics and interactive visualization web application that provides charts, graphs, and alerts when connected to supported data sources\u003C/li>\n\u003C/ul>\n\u003Cp>Together, they form a powerful monitoring stack that provides insights into your cluster’s health and performance.\u003C/p>\n\u003Ch2 id=\"prerequisites\">Prerequisites\u003C/h2>\n\u003Cp>Before we begin, ensure you have:\u003C/p>\n\u003Cul>\n\u003Cli>A running Kubernetes cluster (this guide uses K3s)\u003C/li>\n\u003Cli>\u003Ccode>kubectl\u003C/code> configured to communicate with your cluster\u003C/li>\n\u003Cli>Helm 3 installed\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"installation-using-helm\">Installation using Helm\u003C/h2>\n\u003Cp>The easiest way to install Prometheus and Grafana is using the kube-prometheus-stack Helm chart, which includes:\u003C/p>\n\u003Cul>\n\u003Cli>Prometheus Operator\u003C/li>\n\u003Cli>Prometheus instance\u003C/li>\n\u003Cli>Alertmanager\u003C/li>\n\u003Cli>Grafana\u003C/li>\n\u003Cli>Node Exporter\u003C/li>\n\u003Cli>Kube State Metrics\u003C/li>\n\u003C/ul>\n\u003Cp>Let’s create a namespace and install the stack:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Create a dedicated namespace\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">kubectl\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> create\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> namespace\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> monitoring\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Add the Prometheus community Helm repository\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">helm\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> repo\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> add\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> prometheus-community\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> https://prometheus-community.github.io/helm-charts\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">helm\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> repo\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> update\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Install the kube-prometheus-stack\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">helm\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> install\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> prometheus\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> prometheus-community/kube-prometheus-stack\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> --namespace\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> monitoring\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> --set\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> grafana.adminPassword=your-strong-password\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Replace \u003Ccode>your-strong-password\u003C/code> with a secure password for the Grafana admin user.\u003C/p>\n\u003Ch2 id=\"accessing-the-dashboards\">Accessing the Dashboards\u003C/h2>\n\u003Cp>By default, the services are not exposed outside the cluster. To access them, you can use port-forwarding:\u003C/p>\n\u003Ch3 id=\"grafana\">Grafana\u003C/h3>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">kubectl\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> port-forward\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -n\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> monitoring\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> svc/prometheus-grafana\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 3000:80\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Then access Grafana at \u003Ca href=\"http://localhost:3000\">http://localhost:3000\u003C/a> with username \u003Ccode>admin\u003C/code> and the password you specified during installation.\u003C/p>\n\u003Ch3 id=\"prometheus\">Prometheus\u003C/h3>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">kubectl\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> port-forward\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -n\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> monitoring\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> svc/prometheus-operated\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 9090:9090\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Access the Prometheus UI at \u003Ca href=\"http://localhost:9090\">http://localhost:9090\u003C/a>.\u003C/p>\n\u003Ch2 id=\"setting-up-ingress-optional\">Setting Up Ingress (Optional)\u003C/h2>\n\u003Cp>For production environments, you’ll want to set up proper ingress. Here’s an example using Nginx ingress:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">apiVersion\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> networking.k8s.io/v1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">kind\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Ingress\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">metadata\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> grafana-ingress\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> namespace\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> monitoring\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> annotations\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> kubernetes.io/ingress.class\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> nginx\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> nginx.ingress.kubernetes.io/ssl-redirect\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">true\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> rules\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> host\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> grafana.example.com\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> http\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> paths\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> path\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> pathType\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Prefix\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> backend\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> service\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> prometheus-grafana\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> port\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> number\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 80\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> tls\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> hosts\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> grafana.example.com\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> secretName\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> grafana-tls\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Apply this with \u003Ccode>kubectl apply -f ingress.yaml\u003C/code> after replacing \u003Ccode>grafana.example.com\u003C/code> with your domain.\u003C/p>\n\u003Ch2 id=\"important-dashboards-for-kubernetes\">Important Dashboards for Kubernetes\u003C/h2>\n\u003Cp>Grafana comes with several pre-installed dashboards, but here are some essential ones you should import:\u003C/p>\n\u003Col>\n\u003Cli>\u003Cstrong>Kubernetes Cluster Overview\u003C/strong> (ID: 10856)\u003C/li>\n\u003Cli>\u003Cstrong>Node Exporter Full\u003C/strong> (ID: 1860)\u003C/li>\n\u003Cli>\u003Cstrong>Kubernetes Resource Requests\u003C/strong> (ID: 13770)\u003C/li>\n\u003C/ol>\n\u003Cp>To import a dashboard:\u003C/p>\n\u003Col>\n\u003Cli>Go to Grafana UI\u003C/li>\n\u003Cli>Click on ”+” icon in the sidebar\u003C/li>\n\u003Cli>Select “Import”\u003C/li>\n\u003Cli>Enter the dashboard ID\u003C/li>\n\u003Cli>Click “Load”\u003C/li>\n\u003Cli>Select the Prometheus data source\u003C/li>\n\u003Cli>Click “Import”\u003C/li>\n\u003C/ol>\n\u003Ch2 id=\"setting-up-alerts\">Setting Up Alerts\u003C/h2>\n\u003Cp>Let’s set up a basic alert for node CPU usage:\u003C/p>\n\u003Col>\n\u003Cli>In Grafana, go to Alerting > Alert Rules\u003C/li>\n\u003Cli>Click “New Alert Rule”\u003C/li>\n\u003Cli>Configure the query: \u003Ccode>instance:node_cpu_utilisation:rate5m > 0.8\u003C/code>\u003C/li>\n\u003Cli>Set the condition to: \u003Ccode>IS ABOVE 0.8\u003C/code>\u003C/li>\n\u003Cli>Set evaluation interval: \u003Ccode>1m\u003C/code>\u003C/li>\n\u003Cli>Set “For”: \u003Ccode>5m\u003C/code> (alert will fire if condition is true for 5 minutes)\u003C/li>\n\u003Cli>Add labels and annotations as needed\u003C/li>\n\u003Cli>Save the rule\u003C/li>\n\u003C/ol>\n\u003Ch2 id=\"best-practices\">Best Practices\u003C/h2>\n\u003Col>\n\u003Cli>\u003Cstrong>Resource Limits\u003C/strong>: Set appropriate resource requests and limits for Prometheus and Grafana\u003C/li>\n\u003Cli>\u003Cstrong>Retention Period\u003C/strong>: Configure the retention period based on your storage capacity\u003C/li>\n\u003Cli>\u003Cstrong>Persistent Storage\u003C/strong>: Use persistent volumes for Prometheus data\u003C/li>\n\u003Cli>\u003Cstrong>Federation\u003C/strong>: For large clusters, consider Prometheus federation\u003C/li>\n\u003Cli>\u003Cstrong>Custom Metrics\u003C/strong>: Set up custom metrics for your applications using client libraries\u003C/li>\n\u003C/ol>\n\u003Ch2 id=\"advanced-configuration\">Advanced Configuration\u003C/h2>\n\u003Cp>For a production environment, you’ll want to customize the Helm values. Create a \u003Ccode>values.yaml\u003C/code> file:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">prometheus\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> prometheusSpec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> retention\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 15d\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> resources\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> requests\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> memory\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 2Gi\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> cpu\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 500m\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> limits\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> memory\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 4Gi\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> cpu\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 1000m\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> storageSpec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> volumeClaimTemplate\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> storageClassName\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> standard\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> accessModes\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">ReadWriteOnce\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">]\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> resources\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> requests\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> storage\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 50Gi\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">grafana\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> persistence\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> enabled\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> true\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> size\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 10Gi\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> resources\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> requests\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> memory\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 256Mi\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> cpu\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 100m\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> limits\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> memory\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 512Mi\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> cpu\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 200m\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Then update your Helm release:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">helm\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> upgrade\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> prometheus\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> prometheus-community/kube-prometheus-stack\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> --namespace\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> monitoring\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> -f\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> values.yaml\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"troubleshooting\">Troubleshooting\u003C/h2>\n\u003Ch3 id=\"common-issues\">Common Issues\u003C/h3>\n\u003Col>\n\u003Cli>\u003Cstrong>Insufficient Resources\u003C/strong>: If pods are crashing, check if they have enough resources allocated\u003C/li>\n\u003Cli>\u003Cstrong>Connectivity Issues\u003C/strong>: Ensure services can communicate with each other\u003C/li>\n\u003Cli>\u003Cstrong>Data Retention\u003C/strong>: If Prometheus is losing data, check the storage configuration\u003C/li>\n\u003Cli>\u003Cstrong>Target Scraping\u003C/strong>: If metrics aren’t appearing, check Prometheus targets status\u003C/li>\n\u003C/ol>\n\u003Ch3 id=\"useful-commands\">Useful Commands\u003C/h3>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Check pod status\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">kubectl\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> get\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> pods\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -n\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> monitoring\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Check Prometheus targets\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">kubectl\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> port-forward\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -n\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> monitoring\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> svc/prometheus-operated\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 9090:9090\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Then visit http://localhost:9090/targets\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># View Prometheus logs\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">kubectl\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> logs\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -n\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> monitoring\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> deploy/prometheus-operator\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># View Grafana logs\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">kubectl\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> logs\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -n\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> monitoring\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> deploy/prometheus-grafana\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"conclusion\">Conclusion\u003C/h2>\n\u003Cp>You now have a robust monitoring solution for your Kubernetes cluster. With Prometheus collecting metrics and Grafana visualizing them, you’ll have deep insights into your cluster’s performance and health.\u003C/p>\n\u003Cp>In future articles, we’ll explore more advanced topics like custom exporters, alert integrations, and high availability setups for your monitoring stack.\u003C/p>",{"headings":331,"localImagePaths":373,"remoteImagePaths":374,"frontmatter":375,"imagePaths":377},[332,334,337,338,341,344,346,348,351,354,357,360,363,366,369,372],{"depth":52,"slug":333,"text":315},"monitoring-your-kubernetes-cluster-with-prometheus-and-grafana",{"depth":55,"slug":335,"text":336},"why-prometheus-and-grafana","Why Prometheus and Grafana?",{"depth":55,"slug":193,"text":194},{"depth":55,"slug":339,"text":340},"installation-using-helm","Installation using Helm",{"depth":55,"slug":342,"text":343},"accessing-the-dashboards","Accessing the Dashboards",{"depth":97,"slug":322,"text":345},"Grafana",{"depth":97,"slug":321,"text":347},"Prometheus",{"depth":55,"slug":349,"text":350},"setting-up-ingress-optional","Setting Up Ingress (Optional)",{"depth":55,"slug":352,"text":353},"important-dashboards-for-kubernetes","Important Dashboards for Kubernetes",{"depth":55,"slug":355,"text":356},"setting-up-alerts","Setting Up Alerts",{"depth":55,"slug":358,"text":359},"best-practices","Best Practices",{"depth":55,"slug":361,"text":362},"advanced-configuration","Advanced Configuration",{"depth":55,"slug":364,"text":365},"troubleshooting","Troubleshooting",{"depth":97,"slug":367,"text":368},"common-issues","Common Issues",{"depth":97,"slug":370,"text":371},"useful-commands","Useful Commands",{"depth":55,"slug":162,"text":163},[],[],{"title":315,"description":316,"pubDate":317,"heroImage":318,"category":319,"tags":376,"draft":182},[180,321,322,323,324],[],"prometheus-monitoring.md","cloudflare-tunnel-setup",{"id":379,"data":381,"body":384,"filePath":385,"digest":386,"rendered":387,"legacyId":438},{"title":14,"description":15,"pubDate":382,"heroImage":17,"category":18,"tags":383,"readTime":24},["Date","2025-04-19T00:00:00.000Z"],[20,18,21,22,23],"# Secure Remote Access with Cloudflare Tunnels\n\nCloudflare Tunnels provide a secure way to expose your locally hosted applications and services to the internet without opening ports on your firewall or requiring a static IP address. This guide will show you how to set up Cloudflare Tunnels to securely access your home lab services from anywhere.\n\n## Why Use Cloudflare Tunnels?\n\n- **Security**: No need to open ports on your firewall\n- **Simplicity**: Works behind CGNAT, dynamic IPs, and complex network setups\n- **Performance**: Traffic routed through Cloudflare's global network\n- **Zero Trust**: Integrate with Cloudflare Access for authentication\n\n## Prerequisites\n\n- A Cloudflare account\n- A domain managed by Cloudflare\n- Docker installed (for containerized deployment)\n- Services you want to expose (e.g., web apps, SSH, etc.)\n\n## Setting Up Cloudflare Tunnels\n\n### 1. Install cloudflared\n\nYou can install cloudflared using Docker:\n\n```bash\ndocker pull cloudflare/cloudflared:latest\n```\n\nOr directly on your system:\n\n```bash\n# For Debian/Ubuntu\ncurl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb -o cloudflared.deb\nsudo dpkg -i cloudflared.deb\n\n# For other systems, visit: https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/installation\n```\n\n### 2. Authenticate cloudflared\n\nRun the following command to authenticate:\n\n```bash\ncloudflared tunnel login\n```\n\nThis will open a browser window where you'll need to log in to your Cloudflare account and select the domain you want to use with the tunnel.\n\n### 3. Create a Tunnel\n\nCreate a new tunnel with a meaningful name:\n\n```bash\ncloudflared tunnel create homelab\n```\n\nThis will generate a tunnel ID and credentials file at `~/.cloudflared/`.\n\n### 4. Configure your Tunnel\n\nCreate a config file at `~/.cloudflared/config.yml`:\n\n```yaml\ntunnel: \u003CTUNNEL_ID>\ncredentials-file: /root/.cloudflared/\u003CTUNNEL_ID>.json\n\ningress:\n # Dashboard application\n - hostname: dashboard.yourdomain.com\n service: http://localhost:8080\n \n # Grafana service\n - hostname: grafana.yourdomain.com\n service: http://localhost:3000\n \n # SSH service\n - hostname: ssh.yourdomain.com\n service: ssh://localhost:22\n \n # Catch-all rule, which responds with 404\n - service: http_status:404\n```\n\n### 5. Route Traffic to Your Tunnel\n\nConfigure DNS records to route traffic to your tunnel:\n\n```bash\ncloudflared tunnel route dns homelab dashboard.yourdomain.com\ncloudflared tunnel route dns homelab grafana.yourdomain.com\ncloudflared tunnel route dns homelab ssh.yourdomain.com\n```\n\n### 6. Start the Tunnel\n\nRun the tunnel:\n\n```bash\ncloudflared tunnel run homelab\n```\n\nFor production deployments, you'll want to set up cloudflared as a service:\n\n```bash\n# For systemd-based systems\nsudo cloudflared service install\nsudo systemctl start cloudflared\n```\n\n## Docker Compose Example\n\nFor a containerized deployment, create a `docker-compose.yml` file:\n\n```yaml\nversion: '3.8'\nservices:\n cloudflared:\n image: cloudflare/cloudflared:latest\n container_name: cloudflared\n restart: unless-stopped\n command: tunnel run\n environment:\n - TUNNEL_TOKEN=your_tunnel_token\n volumes:\n - ~/.cloudflared:/etc/cloudflared\n```\n\n## Security Considerations\n\n- Store your credentials file safely; it provides full access to your tunnel\n- Consider using Cloudflare Access for additional authentication\n- Regularly rotate credentials and update cloudflared\n\n## Advanced Configuration\n\n### Zero Trust Access\n\nYou can integrate Cloudflare Tunnels with Cloudflare Access to require authentication:\n\n```yaml\ningress:\n - hostname: dashboard.yourdomain.com\n service: http://localhost:8080\n originRequest:\n noTLSVerify: true\n```\n\nThen, create an Access application in the Cloudflare Zero Trust dashboard to protect this hostname.\n\n### Health Checks\n\nConfigure health checks to ensure your services are running:\n\n```yaml\ningress:\n - hostname: dashboard.yourdomain.com\n service: http://localhost:8080\n originRequest:\n healthCheckEnabled: true\n healthCheckPath: /health\n```\n\n## Conclusion\n\nCloudflare Tunnels provide a secure, reliable way to access your home lab services remotely without exposing your home network to the internet. With the setup described in this guide, you can securely access your services from anywhere in the world.","src/content/blog/cloudflare-tunnel-setup.md","34d0dc77585b210a",{"html":388,"metadata":389},"\u003Ch1 id=\"secure-remote-access-with-cloudflare-tunnels\">Secure Remote Access with Cloudflare Tunnels\u003C/h1>\n\u003Cp>Cloudflare Tunnels provide a secure way to expose your locally hosted applications and services to the internet without opening ports on your firewall or requiring a static IP address. This guide will show you how to set up Cloudflare Tunnels to securely access your home lab services from anywhere.\u003C/p>\n\u003Ch2 id=\"why-use-cloudflare-tunnels\">Why Use Cloudflare Tunnels?\u003C/h2>\n\u003Cul>\n\u003Cli>\u003Cstrong>Security\u003C/strong>: No need to open ports on your firewall\u003C/li>\n\u003Cli>\u003Cstrong>Simplicity\u003C/strong>: Works behind CGNAT, dynamic IPs, and complex network setups\u003C/li>\n\u003Cli>\u003Cstrong>Performance\u003C/strong>: Traffic routed through Cloudflare’s global network\u003C/li>\n\u003Cli>\u003Cstrong>Zero Trust\u003C/strong>: Integrate with Cloudflare Access for authentication\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"prerequisites\">Prerequisites\u003C/h2>\n\u003Cul>\n\u003Cli>A Cloudflare account\u003C/li>\n\u003Cli>A domain managed by Cloudflare\u003C/li>\n\u003Cli>Docker installed (for containerized deployment)\u003C/li>\n\u003Cli>Services you want to expose (e.g., web apps, SSH, etc.)\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"setting-up-cloudflare-tunnels\">Setting Up Cloudflare Tunnels\u003C/h2>\n\u003Ch3 id=\"1-install-cloudflared\">1. Install cloudflared\u003C/h3>\n\u003Cp>You can install cloudflared using Docker:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">docker\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> pull\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> cloudflare/cloudflared:latest\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Or directly on your system:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># For Debian/Ubuntu\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">curl\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -L\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -o\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> cloudflared.deb\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">sudo\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> dpkg\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -i\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> cloudflared.deb\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># For other systems, visit: https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/installation\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"2-authenticate-cloudflared\">2. Authenticate cloudflared\u003C/h3>\n\u003Cp>Run the following command to authenticate:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">cloudflared\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> tunnel\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> login\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>This will open a browser window where you’ll need to log in to your Cloudflare account and select the domain you want to use with the tunnel.\u003C/p>\n\u003Ch3 id=\"3-create-a-tunnel\">3. Create a Tunnel\u003C/h3>\n\u003Cp>Create a new tunnel with a meaningful name:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">cloudflared\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> tunnel\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> create\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> homelab\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>This will generate a tunnel ID and credentials file at \u003Ccode>~/.cloudflared/\u003C/code>.\u003C/p>\n\u003Ch3 id=\"4-configure-your-tunnel\">4. Configure your Tunnel\u003C/h3>\n\u003Cp>Create a config file at \u003Ccode>~/.cloudflared/config.yml\u003C/code>:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">tunnel\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> <TUNNEL_ID>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">credentials-file\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /root/.cloudflared/<TUNNEL_ID>.json\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">ingress\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> # Dashboard application\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> hostname\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> dashboard.yourdomain.com\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> service\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> http://localhost:8080\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> # Grafana service\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> hostname\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> grafana.yourdomain.com\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> service\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> http://localhost:3000\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> # SSH service\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> hostname\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ssh.yourdomain.com\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> service\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ssh://localhost:22\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> # Catch-all rule, which responds with 404\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> service\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> http_status:404\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"5-route-traffic-to-your-tunnel\">5. Route Traffic to Your Tunnel\u003C/h3>\n\u003Cp>Configure DNS records to route traffic to your tunnel:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">cloudflared\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> tunnel\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> route\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> dns\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> homelab\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> dashboard.yourdomain.com\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">cloudflared\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> tunnel\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> route\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> dns\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> homelab\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> grafana.yourdomain.com\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">cloudflared\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> tunnel\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> route\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> dns\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> homelab\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ssh.yourdomain.com\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"6-start-the-tunnel\">6. Start the Tunnel\u003C/h3>\n\u003Cp>Run the tunnel:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">cloudflared\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> tunnel\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> run\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> homelab\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>For production deployments, you’ll want to set up cloudflared as a service:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># For systemd-based systems\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">sudo\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> cloudflared\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> service\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> install\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">sudo\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> systemctl\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> start\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> cloudflared\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"docker-compose-example\">Docker Compose Example\u003C/h2>\n\u003Cp>For a containerized deployment, create a \u003Ccode>docker-compose.yml\u003C/code> file:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">version\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> '\u003C/span>\u003Cspan style=\"color:#F1FA8C\">3.8\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">services\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> cloudflared\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> image\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> cloudflare/cloudflared:latest\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> container_name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> cloudflared\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> restart\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> unless-stopped\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> command\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> tunnel run\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> environment\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> TUNNEL_TOKEN=your_tunnel_token\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> volumes\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ~/.cloudflared:/etc/cloudflared\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"security-considerations\">Security Considerations\u003C/h2>\n\u003Cul>\n\u003Cli>Store your credentials file safely; it provides full access to your tunnel\u003C/li>\n\u003Cli>Consider using Cloudflare Access for additional authentication\u003C/li>\n\u003Cli>Regularly rotate credentials and update cloudflared\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"advanced-configuration\">Advanced Configuration\u003C/h2>\n\u003Ch3 id=\"zero-trust-access\">Zero Trust Access\u003C/h3>\n\u003Cp>You can integrate Cloudflare Tunnels with Cloudflare Access to require authentication:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">ingress\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> hostname\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> dashboard.yourdomain.com\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> service\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> http://localhost:8080\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> originRequest\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> noTLSVerify\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> true\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Then, create an Access application in the Cloudflare Zero Trust dashboard to protect this hostname.\u003C/p>\n\u003Ch3 id=\"health-checks\">Health Checks\u003C/h3>\n\u003Cp>Configure health checks to ensure your services are running:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">ingress\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> hostname\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> dashboard.yourdomain.com\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> service\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> http://localhost:8080\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> originRequest\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> healthCheckEnabled\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> true\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> healthCheckPath\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /health\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"conclusion\">Conclusion\u003C/h2>\n\u003Cp>Cloudflare Tunnels provide a secure, reliable way to access your home lab services remotely without exposing your home network to the internet. With the setup described in this guide, you can securely access your services from anywhere in the world.\u003C/p>",{"headings":390,"localImagePaths":432,"remoteImagePaths":433,"frontmatter":434,"imagePaths":437},[391,393,396,397,400,403,406,409,412,415,418,421,424,425,428,431],{"depth":52,"slug":392,"text":14},"secure-remote-access-with-cloudflare-tunnels",{"depth":55,"slug":394,"text":395},"why-use-cloudflare-tunnels","Why Use Cloudflare Tunnels?",{"depth":55,"slug":193,"text":194},{"depth":55,"slug":398,"text":399},"setting-up-cloudflare-tunnels","Setting Up Cloudflare Tunnels",{"depth":97,"slug":401,"text":402},"1-install-cloudflared","1. Install cloudflared",{"depth":97,"slug":404,"text":405},"2-authenticate-cloudflared","2. Authenticate cloudflared",{"depth":97,"slug":407,"text":408},"3-create-a-tunnel","3. Create a Tunnel",{"depth":97,"slug":410,"text":411},"4-configure-your-tunnel","4. Configure your Tunnel",{"depth":97,"slug":413,"text":414},"5-route-traffic-to-your-tunnel","5. Route Traffic to Your Tunnel",{"depth":97,"slug":416,"text":417},"6-start-the-tunnel","6. Start the Tunnel",{"depth":55,"slug":419,"text":420},"docker-compose-example","Docker Compose Example",{"depth":55,"slug":422,"text":423},"security-considerations","Security Considerations",{"depth":55,"slug":361,"text":362},{"depth":97,"slug":426,"text":427},"zero-trust-access","Zero Trust Access",{"depth":97,"slug":429,"text":430},"health-checks","Health Checks",{"depth":55,"slug":162,"text":163},[],[],{"title":14,"description":15,"pubDate":435,"heroImage":17,"category":18,"tags":436,"readTime":24},["Date","2025-04-19T00:00:00.000Z"],[20,18,21,22,23],[],"cloudflare-tunnel-setup.md","starting-my-digital-garden",{"id":439,"data":441,"body":451,"filePath":452,"digest":453,"rendered":454,"legacyId":476},{"title":442,"description":443,"pubDate":444,"heroImage":445,"category":446,"tags":447,"draft":182},"Starting My Digital Garden","How and why I'm approaching this blog as a digital garden rather than a traditional chronological blog.","2023-10-05","/blog/images/placeholders/default.jpg","Meta",[448,449,450],"digital-garden","knowledge-management","learning-in-public","# Starting My Digital Garden\n\nInstead of creating yet another chronological blog, I've decided to structure this site as a \"digital garden\" - a place where ideas grow and evolve over time.\n\n## What is a Digital Garden?\n\nA digital garden is a collection of notes, articles, and resources that aren't organized strictly by date, but rather by topic and interconnectedness. Unlike traditional blogs where posts are published once and rarely updated, digital gardens embrace the idea of continuous growth and refinement.\n\nKey characteristics of digital gardens include:\n\n- **Living documents**: Content is regularly revisited and updated as my understanding evolves\n- **Non-linear**: Ideas are interconnected through links rather than presented in strict chronology\n- **Varying levels of completion**: Some notes are polished essays, others are rough sketches of ideas\n- **Learning in public**: Sharing my learning process, not just the finished product\n\n## Why a Digital Garden?\n\nThe digital garden approach aligns perfectly with how I learn about and work with technology:\n\n1. **Technology evolves**: My guides and tutorials will evolve alongside the technologies they describe\n2. **Connection between concepts**: Infrastructure, automation, and deployment are deeply interconnected\n3. **Continuous improvement**: I can revisit and enhance articles as I discover better approaches\n4. **Lower barrier to publishing**: I can share work-in-progress ideas without waiting for \"perfection\"\n\n## How This Works\n\nOn this site, you'll find:\n\n- **Posts**: Longer-form articles that explain concepts, provide tutorials, or share insights\n- **Configurations**: Specific configuration guides and setup instructions\n- **Projects**: Documentation of my homelab and technical projects\n\nContent will be interconnected through links and the visualization graph on the homepage. Every post has a \"Last Updated\" date so you can see how recently the information was reviewed.\n\n## A Note on \"Maturity\"\n\nNot all content in a digital garden has the same level of completeness. I'll be using these general states:\n\n- **Seedlings**: Early ideas, rough notes, or work-in-progress\n- **Budding**: Structured content with the main points established but still developing\n- **Evergreen**: Well-developed, comprehensive resources that are regularly maintained\n\nI look forward to growing this digital garden over time and hope you find the content useful on your own technical journey!\n\n---\n\n*This introduction to my digital garden concept was last updated on October 5, 2023.*","src/content/blog/starting-my-digital-garden.md","cdf8de3bdc365618",{"html":455,"metadata":456},"\u003Ch1 id=\"starting-my-digital-garden\">Starting My Digital Garden\u003C/h1>\n\u003Cp>Instead of creating yet another chronological blog, I’ve decided to structure this site as a “digital garden” - a place where ideas grow and evolve over time.\u003C/p>\n\u003Ch2 id=\"what-is-a-digital-garden\">What is a Digital Garden?\u003C/h2>\n\u003Cp>A digital garden is a collection of notes, articles, and resources that aren’t organized strictly by date, but rather by topic and interconnectedness. Unlike traditional blogs where posts are published once and rarely updated, digital gardens embrace the idea of continuous growth and refinement.\u003C/p>\n\u003Cp>Key characteristics of digital gardens include:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Cstrong>Living documents\u003C/strong>: Content is regularly revisited and updated as my understanding evolves\u003C/li>\n\u003Cli>\u003Cstrong>Non-linear\u003C/strong>: Ideas are interconnected through links rather than presented in strict chronology\u003C/li>\n\u003Cli>\u003Cstrong>Varying levels of completion\u003C/strong>: Some notes are polished essays, others are rough sketches of ideas\u003C/li>\n\u003Cli>\u003Cstrong>Learning in public\u003C/strong>: Sharing my learning process, not just the finished product\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"why-a-digital-garden\">Why a Digital Garden?\u003C/h2>\n\u003Cp>The digital garden approach aligns perfectly with how I learn about and work with technology:\u003C/p>\n\u003Col>\n\u003Cli>\u003Cstrong>Technology evolves\u003C/strong>: My guides and tutorials will evolve alongside the technologies they describe\u003C/li>\n\u003Cli>\u003Cstrong>Connection between concepts\u003C/strong>: Infrastructure, automation, and deployment are deeply interconnected\u003C/li>\n\u003Cli>\u003Cstrong>Continuous improvement\u003C/strong>: I can revisit and enhance articles as I discover better approaches\u003C/li>\n\u003Cli>\u003Cstrong>Lower barrier to publishing\u003C/strong>: I can share work-in-progress ideas without waiting for “perfection”\u003C/li>\n\u003C/ol>\n\u003Ch2 id=\"how-this-works\">How This Works\u003C/h2>\n\u003Cp>On this site, you’ll find:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Cstrong>Posts\u003C/strong>: Longer-form articles that explain concepts, provide tutorials, or share insights\u003C/li>\n\u003Cli>\u003Cstrong>Configurations\u003C/strong>: Specific configuration guides and setup instructions\u003C/li>\n\u003Cli>\u003Cstrong>Projects\u003C/strong>: Documentation of my homelab and technical projects\u003C/li>\n\u003C/ul>\n\u003Cp>Content will be interconnected through links and the visualization graph on the homepage. Every post has a “Last Updated” date so you can see how recently the information was reviewed.\u003C/p>\n\u003Ch2 id=\"a-note-on-maturity\">A Note on “Maturity”\u003C/h2>\n\u003Cp>Not all content in a digital garden has the same level of completeness. I’ll be using these general states:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Cstrong>Seedlings\u003C/strong>: Early ideas, rough notes, or work-in-progress\u003C/li>\n\u003Cli>\u003Cstrong>Budding\u003C/strong>: Structured content with the main points established but still developing\u003C/li>\n\u003Cli>\u003Cstrong>Evergreen\u003C/strong>: Well-developed, comprehensive resources that are regularly maintained\u003C/li>\n\u003C/ul>\n\u003Cp>I look forward to growing this digital garden over time and hope you find the content useful on your own technical journey!\u003C/p>\n\u003Chr>\n\u003Cp>\u003Cem>This introduction to my digital garden concept was last updated on October 5, 2023.\u003C/em>\u003C/p>",{"headings":457,"localImagePaths":471,"remoteImagePaths":472,"frontmatter":473,"imagePaths":475},[458,459,462,465,468],{"depth":52,"slug":439,"text":442},{"depth":55,"slug":460,"text":461},"what-is-a-digital-garden","What is a Digital Garden?",{"depth":55,"slug":463,"text":464},"why-a-digital-garden","Why a Digital Garden?",{"depth":55,"slug":466,"text":467},"how-this-works","How This Works",{"depth":55,"slug":469,"text":470},"a-note-on-maturity","A Note on “Maturity”",[],[],{"title":442,"description":443,"pubDate":444,"heroImage":445,"category":446,"tags":474,"draft":182},[448,449,450],[],"starting-my-digital-garden.md","test-post",{"id":477,"data":479,"body":485,"filePath":486,"digest":487,"rendered":488,"legacyId":499},{"title":480,"description":481,"pubDate":482,"heroImage":17,"category":483,"tags":484,"draft":43},"Test Post","This is a test post to verify the blog setup",["Date","2024-03-20T00:00:00.000Z"],"Test",[11],"# Test Post\n\nThis is a test post to verify that the blog setup is working correctly.","src/content/blog/test-post.md","b8d1316cbddb57f8",{"html":489,"metadata":490},"\u003Ch1 id=\"test-post\">Test Post\u003C/h1>\n\u003Cp>This is a test post to verify that the blog setup is working correctly.\u003C/p>",{"headings":491,"localImagePaths":493,"remoteImagePaths":494,"frontmatter":495,"imagePaths":498},[492],{"depth":52,"slug":477,"text":480},[],[],{"title":480,"pubDate":496,"description":481,"category":483,"tags":497,"draft":43,"heroImage":17},["Date","2024-03-20T00:00:00.000Z"],[11],[],"test-post.md","gitea-self-hosted-git",{"id":500,"data":502,"body":512,"filePath":513,"digest":514,"rendered":515,"legacyId":572},{"title":503,"description":504,"pubDate":505,"updatedDate":506,"heroImage":17,"category":507,"tags":508},"Self-Hosting Git with Gitea: Your Own GitHub Alternative","A comprehensive guide to setting up Gitea - a lightweight, self-hosted Git service that gives you full control over your code repositories.",["Date","2025-04-19T00:00:00.000Z"],["Date","2025-04-18T00:00:00.000Z"],"Services",[509,510,511,266,180],"gitea","git","self-hosted","If you're a developer like me who values ownership and privacy, you've probably wondered if there's a way to get the convenience of GitHub or GitLab without handing over your code to a third party. Enter Gitea - a painless, self-hosted Git service written in Go that I've been using for my personal projects for the past year.\n\nLet me walk you through setting up your own Gitea instance and show you why it might be the perfect addition to your development workflow.\n\n## Why Gitea?\n\nFirst, let's talk about why you might want to run your own Git server:\n\n- **Complete control**: Your code, your server, your rules.\n- **Privacy**: Keep sensitive projects completely private.\n- **No limits**: Create as many private repositories as you want.\n- **Lightweight**: Gitea runs smoothly on minimal hardware (even a Raspberry Pi).\n- **GitHub-like experience**: Familiar interface with issues, pull requests, and more.\n\nI've tried several self-hosted Git solutions, but Gitea strikes the perfect balance between features and simplicity. It's like the Goldilocks of Git servers - not too heavy, not too light, just right.\n\n## Getting Started with Gitea\n\n### Option 1: Docker Installation\n\nThe easiest way to get started with Gitea is using Docker. Here's a simple `docker-compose.yml` file to get you up and running:\n\n```yaml\nversion: \"3\"\n\nservices:\n gitea:\n image: gitea/gitea:latest\n container_name: gitea\n environment:\n - USER_UID=1000\n - USER_GID=1000\n - GITEA__database__DB_TYPE=postgres\n - GITEA__database__HOST=db:5432\n - GITEA__database__NAME=gitea\n - GITEA__database__USER=gitea\n - GITEA__database__PASSWD=gitea_password\n restart: always\n volumes:\n - ./gitea:/data\n - /etc/timezone:/etc/timezone:ro\n - /etc/localtime:/etc/localtime:ro\n ports:\n - \"3000:3000\"\n - \"222:22\"\n depends_on:\n - db\n networks:\n - gitea\n\n db:\n image: postgres:14\n container_name: gitea-db\n restart: always\n environment:\n - POSTGRES_USER=gitea\n - POSTGRES_PASSWORD=gitea_password\n - POSTGRES_DB=gitea\n volumes:\n - ./postgres:/var/lib/postgresql/data\n networks:\n - gitea\n\nnetworks:\n gitea:\n external: false\n```\n\nSave this file and run:\n\n```bash\ndocker-compose up -d\n```\n\nYour Gitea instance will be available at `http://localhost:3000`.\n\n### Option 2: Kubernetes Deployment\n\nFor those running a Kubernetes cluster (like me), here's a basic manifest to deploy Gitea:\n\n```yaml\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n name: gitea-data\nspec:\n accessModes:\n - ReadWriteOnce\n resources:\n requests:\n storage: 10Gi\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: gitea\n labels:\n app: gitea\nspec:\n replicas: 1\n selector:\n matchLabels:\n app: gitea\n template:\n metadata:\n labels:\n app: gitea\n spec:\n containers:\n - name: gitea\n image: gitea/gitea:latest\n ports:\n - containerPort: 3000\n - containerPort: 22\n volumeMounts:\n - name: data\n mountPath: /data\n env:\n - name: USER_UID\n value: \"1000\"\n - name: USER_GID\n value: \"1000\"\n volumes:\n - name: data\n persistentVolumeClaim:\n claimName: gitea-data\n---\napiVersion: v1\nkind: Service\nmetadata:\n name: gitea\nspec:\n type: ClusterIP\n ports:\n - port: 3000\n targetPort: 3000\n name: web\n - port: 22\n targetPort: 22\n name: ssh\n selector:\n app: gitea\n```\n\nApply it with:\n\n```bash\nkubectl apply -f gitea.yaml\n```\n\n## Initial Configuration\n\nAfter installation, you'll be greeted with Gitea's setup page. Here are the settings I recommend:\n\n1. **Database Settings**: If you followed the Docker Compose example, your database is already configured.\n\n2. **General Settings**:\n - Set your site title (e.g., \"LaForceIT Git\")\n - Disable user registration unless you're hosting for multiple people\n - Enable caching to improve performance\n\n3. **Admin Account**: Create your admin user with a strong password.\n\nMy configuration looks something like this:\n\n```ini\n[server]\nDOMAIN = git.laforce.it\nSSH_DOMAIN = git.laforce.it\nROOT_URL = https://git.laforce.it/\nDISABLE_SSH = false\nSSH_PORT = 22\n\n[service]\nDISABLE_REGISTRATION = true\nREQUIRE_SIGNIN_VIEW = true\n\n[security]\nINSTALL_LOCK = true\n```\n\n## Integrating with Your Development Workflow\n\nNow that Gitea is running, here's how I integrate it into my workflow:\n\n### 1. Adding Your SSH Key\n\nFirst, add your SSH key to Gitea:\n\n1. Go to Settings > SSH / GPG Keys\n2. Click \"Add Key\"\n3. Paste your public key and give it a name\n\n### 2. Creating Your First Repository\n\n1. Click the \"+\" button in the top right\n2. Select \"New Repository\"\n3. Fill in the details and initialize with a README if desired\n\n### 3. Working with Your Repository\n\nTo clone your new repository:\n\n```bash\ngit clone git@your-gitea-server:username/repo-name.git\n```\n\nNow you can work with it just like any Git repository:\n\n```bash\ncd repo-name\necho \"# My awesome project\" > README.md\ngit add README.md\ngit commit -m \"Update README\"\ngit push origin main\n```\n\n## Advanced Gitea Features\n\nGitea isn't just a basic Git server - it has several powerful features that I use daily:\n\n### CI/CD with Gitea Actions\n\nGitea recently added support for Actions, which are compatible with GitHub Actions workflows. Here's a simple example:\n\n```yaml\nname: Go Build\non: [push, pull_request]\n\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v3\n - name: Set up Go\n uses: actions/setup-go@v4\n with:\n go-version: '1.20'\n - name: Build\n run: go build -v ./...\n - name: Test\n run: go test -v ./...\n```\n\n### Webhooks for Integration\n\nI use webhooks to integrate Gitea with my deployment pipeline. Here's how to set up a simple webhook:\n\n1. Navigate to your repository\n2. Go to Settings > Webhooks > Add Webhook\n3. Select \"Gitea\" or \"Custom\" depending on your needs\n4. Enter the URL of your webhook receiver\n5. Choose which events trigger the webhook\n\n### Mirror Repositories\n\nOne of my favorite features is repository mirroring. I use this to keep a backup of important GitHub repositories:\n\n1. Create a new repository\n2. Go to Settings > Mirror Settings\n3. Enter the URL of the repository you want to mirror\n4. Set the sync interval\n\n## Security Considerations\n\nWhen self-hosting any service, security is a top priority. Here's how I secure my Gitea instance:\n\n1. **Reverse Proxy**: I put Gitea behind Traefik with automatic SSL certificates.\n\n2. **2FA**: Enable two-factor authentication for your admin account.\n\n3. **Regular Backups**: I back up both the Gitea data directory and the database daily.\n\n4. **Updates**: Keep Gitea updated to the latest version to get security fixes.\n\nHere's a sample Traefik configuration for Gitea:\n\n```yaml\napiVersion: traefik.containo.us/v1alpha1\nkind: IngressRoute\nmetadata:\n name: gitea\n namespace: default\nspec:\n entryPoints:\n - websecure\n routes:\n - match: Host(`git.yourdomain.com`)\n kind: Rule\n services:\n - name: gitea\n port: 3000\n tls:\n certResolver: letsencrypt\n```\n\n## Why I Switched from GitHub to Gitea\n\nPeople often ask me why I bother with self-hosting when GitHub offers so much for free. Here are my reasons:\n\n1. **Ownership**: No sudden changes in terms of service affecting my workflow.\n2. **Privacy**: Some projects aren't meant for public hosting.\n3. **Learning**: Managing my own services teaches me valuable skills.\n4. **Integration**: It fits perfectly with my other self-hosted services.\n5. **Performance**: Local Git operations are lightning-fast.\n\n## Wrapping Up\n\nGitea has been a fantastic addition to my self-hosted infrastructure. It's reliable, lightweight, and provides all the features I need without the complexity of larger solutions like GitLab.\n\nWhether you're a privacy enthusiast, a homelab tinkerer, or just someone who wants complete control over your code, Gitea is worth considering. The setup is straightforward, and the rewards are significant.\n\nWhat about you? Are you self-hosting any of your development tools? Let me know in the comments!\n\n---\n\n_This post was last updated on January 18, 2024 with information about Gitea Actions and the latest configuration options._","src/content/blog/gitea-self-hosted-git.md","cb1dec0a41179cba",{"html":516,"metadata":517},"\u003Cp>If you’re a developer like me who values ownership and privacy, you’ve probably wondered if there’s a way to get the convenience of GitHub or GitLab without handing over your code to a third party. Enter Gitea - a painless, self-hosted Git service written in Go that I’ve been using for my personal projects for the past year.\u003C/p>\n\u003Cp>Let me walk you through setting up your own Gitea instance and show you why it might be the perfect addition to your development workflow.\u003C/p>\n\u003Ch2 id=\"why-gitea\">Why Gitea?\u003C/h2>\n\u003Cp>First, let’s talk about why you might want to run your own Git server:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Cstrong>Complete control\u003C/strong>: Your code, your server, your rules.\u003C/li>\n\u003Cli>\u003Cstrong>Privacy\u003C/strong>: Keep sensitive projects completely private.\u003C/li>\n\u003Cli>\u003Cstrong>No limits\u003C/strong>: Create as many private repositories as you want.\u003C/li>\n\u003Cli>\u003Cstrong>Lightweight\u003C/strong>: Gitea runs smoothly on minimal hardware (even a Raspberry Pi).\u003C/li>\n\u003Cli>\u003Cstrong>GitHub-like experience\u003C/strong>: Familiar interface with issues, pull requests, and more.\u003C/li>\n\u003C/ul>\n\u003Cp>I’ve tried several self-hosted Git solutions, but Gitea strikes the perfect balance between features and simplicity. It’s like the Goldilocks of Git servers - not too heavy, not too light, just right.\u003C/p>\n\u003Ch2 id=\"getting-started-with-gitea\">Getting Started with Gitea\u003C/h2>\n\u003Ch3 id=\"option-1-docker-installation\">Option 1: Docker Installation\u003C/h3>\n\u003Cp>The easiest way to get started with Gitea is using Docker. Here’s a simple \u003Ccode>docker-compose.yml\u003C/code> file to get you up and running:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">version\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">3\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">services\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> gitea\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> image\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> gitea/gitea:latest\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> container_name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> gitea\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> environment\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> USER_UID=1000\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> USER_GID=1000\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> GITEA__database__DB_TYPE=postgres\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> GITEA__database__HOST=db:5432\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> GITEA__database__NAME=gitea\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> GITEA__database__USER=gitea\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> GITEA__database__PASSWD=gitea_password\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> restart\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> always\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> volumes\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ./gitea:/data\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /etc/timezone:/etc/timezone:ro\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /etc/localtime:/etc/localtime:ro\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> ports\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">3000:3000\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">222:22\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> depends_on\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> db\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> networks\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> gitea\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> db\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> image\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> postgres:14\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> container_name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> gitea-db\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> restart\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> always\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> environment\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> POSTGRES_USER=gitea\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> POSTGRES_PASSWORD=gitea_password\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> POSTGRES_DB=gitea\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> volumes\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ./postgres:/var/lib/postgresql/data\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> networks\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> gitea\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">networks\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> gitea\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> external\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> false\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Save this file and run:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">docker-compose\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> up\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -d\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Your Gitea instance will be available at \u003Ccode>http://localhost:3000\u003C/code>.\u003C/p>\n\u003Ch3 id=\"option-2-kubernetes-deployment\">Option 2: Kubernetes Deployment\u003C/h3>\n\u003Cp>For those running a Kubernetes cluster (like me), here’s a basic manifest to deploy Gitea:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">apiVersion\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> v1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">kind\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> PersistentVolumeClaim\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">metadata\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> gitea-data\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> accessModes\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ReadWriteOnce\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> resources\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> requests\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> storage\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 10Gi\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">---\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">apiVersion\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> apps/v1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">kind\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Deployment\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">metadata\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> gitea\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> labels\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> app\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> gitea\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> replicas\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> selector\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> matchLabels\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> app\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> gitea\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> template\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> metadata\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> labels\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> app\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> gitea\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> containers\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> gitea\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> image\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> gitea/gitea:latest\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> ports\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> containerPort\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 3000\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> containerPort\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 22\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> volumeMounts\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> data\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> mountPath\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /data\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> env\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> USER_UID\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> value\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">1000\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> USER_GID\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> value\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">1000\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> volumes\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> data\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> persistentVolumeClaim\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> claimName\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> gitea-data\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">---\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">apiVersion\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> v1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">kind\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Service\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">metadata\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> gitea\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> type\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ClusterIP\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> ports\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> port\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 3000\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> targetPort\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 3000\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> web\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> port\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 22\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> targetPort\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 22\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ssh\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> selector\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> app\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> gitea\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Apply it with:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">kubectl\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> apply\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -f\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> gitea.yaml\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"initial-configuration\">Initial Configuration\u003C/h2>\n\u003Cp>After installation, you’ll be greeted with Gitea’s setup page. Here are the settings I recommend:\u003C/p>\n\u003Col>\n\u003Cli>\n\u003Cp>\u003Cstrong>Database Settings\u003C/strong>: If you followed the Docker Compose example, your database is already configured.\u003C/p>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>General Settings\u003C/strong>:\u003C/p>\n\u003Cul>\n\u003Cli>Set your site title (e.g., “LaForceIT Git”)\u003C/li>\n\u003Cli>Disable user registration unless you’re hosting for multiple people\u003C/li>\n\u003Cli>Enable caching to improve performance\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>Admin Account\u003C/strong>: Create your admin user with a strong password.\u003C/p>\n\u003C/li>\n\u003C/ol>\n\u003Cp>My configuration looks something like this:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"ini\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">[server]\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\">DOMAIN\u003C/span>\u003Cspan style=\"color:#FF79C6\"> =\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> git.laforce.it\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\">SSH_DOMAIN\u003C/span>\u003Cspan style=\"color:#FF79C6\"> =\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> git.laforce.it\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\">ROOT_URL\u003C/span>\u003Cspan style=\"color:#FF79C6\"> =\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> https://git.laforce.it/\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\">DISABLE_SSH\u003C/span>\u003Cspan style=\"color:#FF79C6\"> =\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> false\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\">SSH_PORT\u003C/span>\u003Cspan style=\"color:#FF79C6\"> =\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> 22\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">[service]\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\">DISABLE_REGISTRATION\u003C/span>\u003Cspan style=\"color:#FF79C6\"> =\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> true\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\">REQUIRE_SIGNIN_VIEW\u003C/span>\u003Cspan style=\"color:#FF79C6\"> =\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> true\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">[security]\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\">INSTALL_LOCK\u003C/span>\u003Cspan style=\"color:#FF79C6\"> =\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> true\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"integrating-with-your-development-workflow\">Integrating with Your Development Workflow\u003C/h2>\n\u003Cp>Now that Gitea is running, here’s how I integrate it into my workflow:\u003C/p>\n\u003Ch3 id=\"1-adding-your-ssh-key\">1. Adding Your SSH Key\u003C/h3>\n\u003Cp>First, add your SSH key to Gitea:\u003C/p>\n\u003Col>\n\u003Cli>Go to Settings > SSH / GPG Keys\u003C/li>\n\u003Cli>Click “Add Key”\u003C/li>\n\u003Cli>Paste your public key and give it a name\u003C/li>\n\u003C/ol>\n\u003Ch3 id=\"2-creating-your-first-repository\">2. Creating Your First Repository\u003C/h3>\n\u003Col>\n\u003Cli>Click the ”+” button in the top right\u003C/li>\n\u003Cli>Select “New Repository”\u003C/li>\n\u003Cli>Fill in the details and initialize with a README if desired\u003C/li>\n\u003C/ol>\n\u003Ch3 id=\"3-working-with-your-repository\">3. Working with Your Repository\u003C/h3>\n\u003Cp>To clone your new repository:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">git\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> clone\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> git@your-gitea-server:username/repo-name.git\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Now you can work with it just like any Git repository:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">cd\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> repo-name\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">echo\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\"># My awesome project\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\"> >\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> README.md\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">git\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> add\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> README.md\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">git\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> commit\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -m\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Update README\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">git\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> push\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> origin\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> main\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"advanced-gitea-features\">Advanced Gitea Features\u003C/h2>\n\u003Cp>Gitea isn’t just a basic Git server - it has several powerful features that I use daily:\u003C/p>\n\u003Ch3 id=\"cicd-with-gitea-actions\">CI/CD with Gitea Actions\u003C/h3>\n\u003Cp>Gitea recently added support for Actions, which are compatible with GitHub Actions workflows. Here’s a simple example:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Go Build\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\">on\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003Cspan style=\"color:#F1FA8C\">push\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#F1FA8C\">pull_request\u003C/span>\u003Cspan style=\"color:#F8F8F2\">]\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">jobs\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> build\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> runs-on\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ubuntu-latest\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> steps\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> uses\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> actions/checkout@v3\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Set up Go\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> uses\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> actions/setup-go@v4\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> with\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> go-version\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> '\u003C/span>\u003Cspan style=\"color:#F1FA8C\">1.20\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Build\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> run\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> go build -v ./...\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Test\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> run\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> go test -v ./...\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"webhooks-for-integration\">Webhooks for Integration\u003C/h3>\n\u003Cp>I use webhooks to integrate Gitea with my deployment pipeline. Here’s how to set up a simple webhook:\u003C/p>\n\u003Col>\n\u003Cli>Navigate to your repository\u003C/li>\n\u003Cli>Go to Settings > Webhooks > Add Webhook\u003C/li>\n\u003Cli>Select “Gitea” or “Custom” depending on your needs\u003C/li>\n\u003Cli>Enter the URL of your webhook receiver\u003C/li>\n\u003Cli>Choose which events trigger the webhook\u003C/li>\n\u003C/ol>\n\u003Ch3 id=\"mirror-repositories\">Mirror Repositories\u003C/h3>\n\u003Cp>One of my favorite features is repository mirroring. I use this to keep a backup of important GitHub repositories:\u003C/p>\n\u003Col>\n\u003Cli>Create a new repository\u003C/li>\n\u003Cli>Go to Settings > Mirror Settings\u003C/li>\n\u003Cli>Enter the URL of the repository you want to mirror\u003C/li>\n\u003Cli>Set the sync interval\u003C/li>\n\u003C/ol>\n\u003Ch2 id=\"security-considerations\">Security Considerations\u003C/h2>\n\u003Cp>When self-hosting any service, security is a top priority. Here’s how I secure my Gitea instance:\u003C/p>\n\u003Col>\n\u003Cli>\n\u003Cp>\u003Cstrong>Reverse Proxy\u003C/strong>: I put Gitea behind Traefik with automatic SSL certificates.\u003C/p>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>2FA\u003C/strong>: Enable two-factor authentication for your admin account.\u003C/p>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>Regular Backups\u003C/strong>: I back up both the Gitea data directory and the database daily.\u003C/p>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>Updates\u003C/strong>: Keep Gitea updated to the latest version to get security fixes.\u003C/p>\n\u003C/li>\n\u003C/ol>\n\u003Cp>Here’s a sample Traefik configuration for Gitea:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">apiVersion\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> traefik.containo.us/v1alpha1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">kind\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> IngressRoute\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">metadata\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> gitea\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> namespace\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> default\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> entryPoints\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> websecure\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> routes\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> match\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Host(`git.yourdomain.com`)\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> kind\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Rule\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> services\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> gitea\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> port\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 3000\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> tls\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> certResolver\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> letsencrypt\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"why-i-switched-from-github-to-gitea\">Why I Switched from GitHub to Gitea\u003C/h2>\n\u003Cp>People often ask me why I bother with self-hosting when GitHub offers so much for free. Here are my reasons:\u003C/p>\n\u003Col>\n\u003Cli>\u003Cstrong>Ownership\u003C/strong>: No sudden changes in terms of service affecting my workflow.\u003C/li>\n\u003Cli>\u003Cstrong>Privacy\u003C/strong>: Some projects aren’t meant for public hosting.\u003C/li>\n\u003Cli>\u003Cstrong>Learning\u003C/strong>: Managing my own services teaches me valuable skills.\u003C/li>\n\u003Cli>\u003Cstrong>Integration\u003C/strong>: It fits perfectly with my other self-hosted services.\u003C/li>\n\u003Cli>\u003Cstrong>Performance\u003C/strong>: Local Git operations are lightning-fast.\u003C/li>\n\u003C/ol>\n\u003Ch2 id=\"wrapping-up\">Wrapping Up\u003C/h2>\n\u003Cp>Gitea has been a fantastic addition to my self-hosted infrastructure. It’s reliable, lightweight, and provides all the features I need without the complexity of larger solutions like GitLab.\u003C/p>\n\u003Cp>Whether you’re a privacy enthusiast, a homelab tinkerer, or just someone who wants complete control over your code, Gitea is worth considering. The setup is straightforward, and the rewards are significant.\u003C/p>\n\u003Cp>What about you? Are you self-hosting any of your development tools? Let me know in the comments!\u003C/p>\n\u003Chr>\n\u003Cp>\u003Cem>This post was last updated on January 18, 2024 with information about Gitea Actions and the latest configuration options.\u003C/em>\u003C/p>",{"headings":518,"localImagePaths":565,"remoteImagePaths":566,"frontmatter":567,"imagePaths":571},[519,522,525,528,531,534,537,540,543,546,549,552,555,558,559,562],{"depth":55,"slug":520,"text":521},"why-gitea","Why Gitea?",{"depth":55,"slug":523,"text":524},"getting-started-with-gitea","Getting Started with Gitea",{"depth":97,"slug":526,"text":527},"option-1-docker-installation","Option 1: Docker Installation",{"depth":97,"slug":529,"text":530},"option-2-kubernetes-deployment","Option 2: Kubernetes Deployment",{"depth":55,"slug":532,"text":533},"initial-configuration","Initial Configuration",{"depth":55,"slug":535,"text":536},"integrating-with-your-development-workflow","Integrating with Your Development Workflow",{"depth":97,"slug":538,"text":539},"1-adding-your-ssh-key","1. Adding Your SSH Key",{"depth":97,"slug":541,"text":542},"2-creating-your-first-repository","2. Creating Your First Repository",{"depth":97,"slug":544,"text":545},"3-working-with-your-repository","3. Working with Your Repository",{"depth":55,"slug":547,"text":548},"advanced-gitea-features","Advanced Gitea Features",{"depth":97,"slug":550,"text":551},"cicd-with-gitea-actions","CI/CD with Gitea Actions",{"depth":97,"slug":553,"text":554},"webhooks-for-integration","Webhooks for Integration",{"depth":97,"slug":556,"text":557},"mirror-repositories","Mirror Repositories",{"depth":55,"slug":422,"text":423},{"depth":55,"slug":560,"text":561},"why-i-switched-from-github-to-gitea","Why I Switched from GitHub to Gitea",{"depth":55,"slug":563,"text":564},"wrapping-up","Wrapping Up",[],[],{"title":503,"description":504,"pubDate":568,"updatedDate":569,"category":507,"tags":570,"heroImage":17},["Date","2025-04-19T00:00:00.000Z"],["Date","2025-04-18T00:00:00.000Z"],[509,510,511,266,180],[],"gitea-self-hosted-git.md","filebrowser-setup",{"id":573,"data":575,"body":584,"filePath":585,"digest":586,"rendered":587,"legacyId":626},{"title":576,"description":577,"pubDate":578,"updatedDate":579,"heroImage":17,"category":507,"tags":580},"Setting Up FileBrowser for Self-Hosted File Management","A step-by-step guide to deploying and configuring FileBrowser for secure, user-friendly file management in your home lab environment.",["Date","2025-04-19T00:00:00.000Z"],["Date","2025-04-18T00:00:00.000Z"],[581,511,180,582,583],"filebrowser","docker","file-management","I've said it before, and I'll say it again - the journey to a well-organized digital life begins with proper file management. If you're like me, you've got files scattered across multiple devices, cloud services, and servers. What if I told you there's a lightweight, sleek solution that puts you back in control without relying on third-party services?\n\nEnter [FileBrowser](https://filebrowser.org/), a simple yet powerful self-hosted file management interface that I've been using in my home lab for the past few months. Let me show you how to set it up and some cool ways I'm using it.\n\n## What is FileBrowser?\n\nFileBrowser is an open-source, single binary file manager with a clean web interface that lets you:\n\n- Access and manage files from any device with a browser\n- Share files with customizable permissions\n- Edit files directly in the browser\n- Perform basic file operations (copy, move, delete, upload, download)\n- Search through your files and folders\n\nThe best part? It's lightweight (\u003C 20MB), written in Go, and runs on pretty much anything - from a Raspberry Pi to your Kubernetes cluster.\n\n## Getting Started with FileBrowser\n\n### Option 1: Docker Deployment\n\nFor the Docker enthusiasts (like me), here's how to get FileBrowser up and running in seconds:\n\n```bash\ndocker run -d \\\n --name filebrowser \\\n -v /path/to/your/files:/srv \\\n -v /path/to/filebrowser/database:/database \\\n -e PUID=$(id -u) \\\n -e PGID=$(id -g) \\\n -p 8080:80 \\\n filebrowser/filebrowser:latest\n```\n\nThis will start FileBrowser on port 8080, with your files mounted at `/srv` inside the container.\n\n### Option 2: Kubernetes Deployment with Helm\n\nFor my fellow Kubernetes fanatics, here's a simple Helm chart deployment:\n\n```yaml\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: filebrowser\n labels:\n app: filebrowser\nspec:\n replicas: 1\n selector:\n matchLabels:\n app: filebrowser\n template:\n metadata:\n labels:\n app: filebrowser\n spec:\n containers:\n - name: filebrowser\n image: filebrowser/filebrowser:latest\n ports:\n - containerPort: 80\n volumeMounts:\n - name: config\n mountPath: /database\n - name: data\n mountPath: /srv\n volumes:\n - name: config\n persistentVolumeClaim:\n claimName: filebrowser-config\n - name: data\n persistentVolumeClaim:\n claimName: filebrowser-data\n---\napiVersion: v1\nkind: Service\nmetadata:\n name: filebrowser\nspec:\n type: ClusterIP\n ports:\n - port: 80\n targetPort: 80\n selector:\n app: filebrowser\n```\n\nDon't forget to create the necessary PVCs for your configuration and data.\n\n## Configuring FileBrowser\n\nOnce you have FileBrowser running, you can access it at `http://your-server:8080`. The default credentials are:\n\n- Username: `admin`\n- Password: `admin`\n\n**Pro tip**: Change these immediately! You can do this through the UI or by using the FileBrowser CLI.\n\n### Custom Configuration\n\nYou can customize FileBrowser by modifying the configuration file. Here's what my config looks like:\n\n```json\n{\n \"port\": 80,\n \"baseURL\": \"\",\n \"address\": \"\",\n \"log\": \"stdout\",\n \"database\": \"/database/filebrowser.db\",\n \"root\": \"/srv\",\n \"auth\": {\n \"method\": \"json\",\n \"header\": \"\"\n },\n \"branding\": {\n \"name\": \"LaForceIT Files\",\n \"disableExternal\": false,\n \"files\": \"\",\n \"theme\": \"dark\"\n },\n \"cors\": {\n \"enabled\": false,\n \"credentials\": false,\n \"allowedHosts\": []\n }\n}\n```\n\n## Securing FileBrowser\n\nSecurity is crucial, especially when hosting a file manager. Here's how I secure my FileBrowser instance:\n\n1. **Reverse Proxy**: I put FileBrowser behind a reverse proxy (Traefik) with SSL encryption.\n\n2. **Authentication**: I've integrated with my Authelia setup for SSO across my services.\n\n3. **User Isolation**: I create separate users with their own root directories to keep things isolated.\n\nHere's a sample Traefik configuration for FileBrowser:\n\n```yaml\napiVersion: traefik.containo.us/v1alpha1\nkind: IngressRoute\nmetadata:\n name: filebrowser\n namespace: default\nspec:\n entryPoints:\n - websecure\n routes:\n - match: Host(`files.yourdomain.com`)\n kind: Rule\n services:\n - name: filebrowser\n port: 80\n middlewares:\n - name: auth-middleware\n tls:\n certResolver: letsencrypt\n```\n\n## My Top 5 FileBrowser Use Cases\n\n1. **Home Media Management**: I organize my photos, music, and video collections.\n\n2. **Document Repository**: A central place for important documents that I can access from anywhere.\n\n3. **Code Snippet Library**: I keep commonly used code snippets organized by language and project.\n\n4. **Backup Verification**: An easy way to browse my automated backups to verify they're working.\n\n5. **Sharing Files**: When I need to share large files with friends or family, I create a temporary user with limited access.\n\n## Power User Tips\n\nHere are some tricks I've learned along the way:\n\n- **Keyboard Shortcuts**: Press `?` in the UI to see all available shortcuts.\n- **Custom Branding**: Personalize the look and feel by setting a custom name and logo in the config.\n- **Multiple Instances**: Run multiple instances for different purposes (e.g., one for media, one for documents).\n- **Command Runner**: Use the built-in command runner to execute shell scripts on your server.\n\n## Wrapping Up\n\nFileBrowser has become an essential part of my home lab setup. It's lightweight, fast, and just gets the job done without unnecessary complexity. Whether you're a home lab enthusiast or just looking for a simple way to manage your files, FileBrowser is worth checking out.\n\nWhat file management solution are you using? Let me know in the comments!\n\n---\n\n_This post was last updated on December 15, 2023 with the latest FileBrowser configuration options and security recommendations._","src/content/blog/filebrowser-setup.md","61d497d83c4e62a7",{"html":588,"metadata":589},"\u003Cp>I’ve said it before, and I’ll say it again - the journey to a well-organized digital life begins with proper file management. If you’re like me, you’ve got files scattered across multiple devices, cloud services, and servers. What if I told you there’s a lightweight, sleek solution that puts you back in control without relying on third-party services?\u003C/p>\n\u003Cp>Enter \u003Ca href=\"https://filebrowser.org/\">FileBrowser\u003C/a>, a simple yet powerful self-hosted file management interface that I’ve been using in my home lab for the past few months. Let me show you how to set it up and some cool ways I’m using it.\u003C/p>\n\u003Ch2 id=\"what-is-filebrowser\">What is FileBrowser?\u003C/h2>\n\u003Cp>FileBrowser is an open-source, single binary file manager with a clean web interface that lets you:\u003C/p>\n\u003Cul>\n\u003Cli>Access and manage files from any device with a browser\u003C/li>\n\u003Cli>Share files with customizable permissions\u003C/li>\n\u003Cli>Edit files directly in the browser\u003C/li>\n\u003Cli>Perform basic file operations (copy, move, delete, upload, download)\u003C/li>\n\u003Cli>Search through your files and folders\u003C/li>\n\u003C/ul>\n\u003Cp>The best part? It’s lightweight (< 20MB), written in Go, and runs on pretty much anything - from a Raspberry Pi to your Kubernetes cluster.\u003C/p>\n\u003Ch2 id=\"getting-started-with-filebrowser\">Getting Started with FileBrowser\u003C/h2>\n\u003Ch3 id=\"option-1-docker-deployment\">Option 1: Docker Deployment\u003C/h3>\n\u003Cp>For the Docker enthusiasts (like me), here’s how to get FileBrowser up and running in seconds:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">docker\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> run\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -d\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> --name\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> filebrowser\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> -v\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /path/to/your/files:/srv\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> -v\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /path/to/filebrowser/database:/database\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> -e\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> PUID=\u003C/span>\u003Cspan style=\"color:#F8F8F2\">$(\u003C/span>\u003Cspan style=\"color:#50FA7B\">id\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -u\u003C/span>\u003Cspan style=\"color:#F8F8F2\">) \u003C/span>\u003Cspan style=\"color:#FF79C6\">\\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> -e\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> PGID=\u003C/span>\u003Cspan style=\"color:#F8F8F2\">$(\u003C/span>\u003Cspan style=\"color:#50FA7B\">id\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -g\u003C/span>\u003Cspan style=\"color:#F8F8F2\">) \u003C/span>\u003Cspan style=\"color:#FF79C6\">\\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> -p\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 8080:80\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> filebrowser/filebrowser:latest\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>This will start FileBrowser on port 8080, with your files mounted at \u003Ccode>/srv\u003C/code> inside the container.\u003C/p>\n\u003Ch3 id=\"option-2-kubernetes-deployment-with-helm\">Option 2: Kubernetes Deployment with Helm\u003C/h3>\n\u003Cp>For my fellow Kubernetes fanatics, here’s a simple Helm chart deployment:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">apiVersion\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> apps/v1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">kind\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Deployment\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">metadata\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> filebrowser\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> labels\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> app\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> filebrowser\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> replicas\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> selector\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> matchLabels\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> app\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> filebrowser\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> template\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> metadata\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> labels\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> app\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> filebrowser\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> containers\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> filebrowser\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> image\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> filebrowser/filebrowser:latest\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> ports\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> containerPort\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 80\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> volumeMounts\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> config\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> mountPath\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /database\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> data\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> mountPath\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /srv\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> volumes\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> config\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> persistentVolumeClaim\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> claimName\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> filebrowser-config\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> data\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> persistentVolumeClaim\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> claimName\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> filebrowser-data\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">---\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">apiVersion\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> v1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">kind\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Service\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">metadata\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> filebrowser\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> type\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ClusterIP\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> ports\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> port\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 80\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> targetPort\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 80\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> selector\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> app\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> filebrowser\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Don’t forget to create the necessary PVCs for your configuration and data.\u003C/p>\n\u003Ch2 id=\"configuring-filebrowser\">Configuring FileBrowser\u003C/h2>\n\u003Cp>Once you have FileBrowser running, you can access it at \u003Ccode>http://your-server:8080\u003C/code>. The default credentials are:\u003C/p>\n\u003Cul>\n\u003Cli>Username: \u003Ccode>admin\u003C/code>\u003C/li>\n\u003Cli>Password: \u003Ccode>admin\u003C/code>\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>Pro tip\u003C/strong>: Change these immediately! You can do this through the UI or by using the FileBrowser CLI.\u003C/p>\n\u003Ch3 id=\"custom-configuration\">Custom Configuration\u003C/h3>\n\u003Cp>You can customize FileBrowser by modifying the configuration file. Here’s what my config looks like:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"json\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">{\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">port\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 80\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">baseURL\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">address\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">log\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">stdout\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">database\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">/database/filebrowser.db\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">root\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">/srv\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">auth\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">method\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">json\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">header\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">branding\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">name\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">LaForceIT Files\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">disableExternal\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> false\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">files\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">theme\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">dark\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">cors\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">enabled\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> false\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">credentials\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> false\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">allowedHosts\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> []\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">}\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"securing-filebrowser\">Securing FileBrowser\u003C/h2>\n\u003Cp>Security is crucial, especially when hosting a file manager. Here’s how I secure my FileBrowser instance:\u003C/p>\n\u003Col>\n\u003Cli>\n\u003Cp>\u003Cstrong>Reverse Proxy\u003C/strong>: I put FileBrowser behind a reverse proxy (Traefik) with SSL encryption.\u003C/p>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>Authentication\u003C/strong>: I’ve integrated with my Authelia setup for SSO across my services.\u003C/p>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>User Isolation\u003C/strong>: I create separate users with their own root directories to keep things isolated.\u003C/p>\n\u003C/li>\n\u003C/ol>\n\u003Cp>Here’s a sample Traefik configuration for FileBrowser:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">apiVersion\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> traefik.containo.us/v1alpha1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">kind\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> IngressRoute\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">metadata\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> filebrowser\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> namespace\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> default\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> entryPoints\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> websecure\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> routes\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> match\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Host(`files.yourdomain.com`)\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> kind\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Rule\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> services\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> filebrowser\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> port\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 80\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> middlewares\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> auth-middleware\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> tls\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> certResolver\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> letsencrypt\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"my-top-5-filebrowser-use-cases\">My Top 5 FileBrowser Use Cases\u003C/h2>\n\u003Col>\n\u003Cli>\n\u003Cp>\u003Cstrong>Home Media Management\u003C/strong>: I organize my photos, music, and video collections.\u003C/p>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>Document Repository\u003C/strong>: A central place for important documents that I can access from anywhere.\u003C/p>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>Code Snippet Library\u003C/strong>: I keep commonly used code snippets organized by language and project.\u003C/p>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>Backup Verification\u003C/strong>: An easy way to browse my automated backups to verify they’re working.\u003C/p>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>Sharing Files\u003C/strong>: When I need to share large files with friends or family, I create a temporary user with limited access.\u003C/p>\n\u003C/li>\n\u003C/ol>\n\u003Ch2 id=\"power-user-tips\">Power User Tips\u003C/h2>\n\u003Cp>Here are some tricks I’ve learned along the way:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Cstrong>Keyboard Shortcuts\u003C/strong>: Press \u003Ccode>?\u003C/code> in the UI to see all available shortcuts.\u003C/li>\n\u003Cli>\u003Cstrong>Custom Branding\u003C/strong>: Personalize the look and feel by setting a custom name and logo in the config.\u003C/li>\n\u003Cli>\u003Cstrong>Multiple Instances\u003C/strong>: Run multiple instances for different purposes (e.g., one for media, one for documents).\u003C/li>\n\u003Cli>\u003Cstrong>Command Runner\u003C/strong>: Use the built-in command runner to execute shell scripts on your server.\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"wrapping-up\">Wrapping Up\u003C/h2>\n\u003Cp>FileBrowser has become an essential part of my home lab setup. It’s lightweight, fast, and just gets the job done without unnecessary complexity. Whether you’re a home lab enthusiast or just looking for a simple way to manage your files, FileBrowser is worth checking out.\u003C/p>\n\u003Cp>What file management solution are you using? Let me know in the comments!\u003C/p>\n\u003Chr>\n\u003Cp>\u003Cem>This post was last updated on December 15, 2023 with the latest FileBrowser configuration options and security recommendations.\u003C/em>\u003C/p>",{"headings":590,"localImagePaths":619,"remoteImagePaths":620,"frontmatter":621,"imagePaths":625},[591,594,597,600,603,606,609,612,615,618],{"depth":55,"slug":592,"text":593},"what-is-filebrowser","What is FileBrowser?",{"depth":55,"slug":595,"text":596},"getting-started-with-filebrowser","Getting Started with FileBrowser",{"depth":97,"slug":598,"text":599},"option-1-docker-deployment","Option 1: Docker Deployment",{"depth":97,"slug":601,"text":602},"option-2-kubernetes-deployment-with-helm","Option 2: Kubernetes Deployment with Helm",{"depth":55,"slug":604,"text":605},"configuring-filebrowser","Configuring FileBrowser",{"depth":97,"slug":607,"text":608},"custom-configuration","Custom Configuration",{"depth":55,"slug":610,"text":611},"securing-filebrowser","Securing FileBrowser",{"depth":55,"slug":613,"text":614},"my-top-5-filebrowser-use-cases","My Top 5 FileBrowser Use Cases",{"depth":55,"slug":616,"text":617},"power-user-tips","Power User Tips",{"depth":55,"slug":563,"text":564},[],[],{"title":576,"description":577,"pubDate":622,"updatedDate":623,"category":507,"tags":624,"heroImage":17},["Date","2025-04-19T00:00:00.000Z"],["Date","2025-04-18T00:00:00.000Z"],[581,511,180,582,583],[],"filebrowser-setup.md","rancher-kubernetes-management",{"id":627,"data":629,"body":637,"filePath":638,"digest":639,"rendered":640,"legacyId":700},{"title":630,"description":631,"pubDate":632,"updatedDate":633,"heroImage":17,"category":507,"tags":634},"Managing Kubernetes with Rancher: The Home Lab Way","How to set up, configure, and get the most out of Rancher for managing your home Kubernetes clusters",["Date","2025-04-19T00:00:00.000Z"],["Date","2025-04-18T00:00:00.000Z"],[635,180,181,266,636],"rancher","containers","I've been running Kubernetes at home for years now, and I've tried just about every management tool out there. From kubectl and a bunch of YAML files to various dashboards and UIs, I've experimented with it all. But the one tool that's been a constant in my home lab journey is [Rancher](https://rancher.com/) - a complete container management platform that makes Kubernetes management almost... dare I say it... enjoyable?\n\nToday, I want to walk you through setting up Rancher in your home lab and show you some of the features that have made it indispensable for me.\n\n## What is Rancher and Why Should You Care?\n\nRancher is an open-source platform for managing Kubernetes clusters. Think of it as mission control for all your container workloads. It gives you:\n\n- A unified interface for managing multiple clusters (perfect if you're running different K8s distros)\n- Simplified deployment of applications via apps & marketplace\n- Built-in monitoring, logging, and alerting\n- User management and role-based access control\n- A clean, intuitive UI that's actually useful (rare in the Kubernetes world!)\n\nIf you're running even a single Kubernetes cluster at home, Rancher can save you countless hours of typing `kubectl` commands and editing YAML files by hand.\n\n## Setting Up Rancher in Your Home Lab\n\nThere are several ways to deploy Rancher, but I'll focus on two approaches that work well for home labs.\n\n### Option 1: Docker Deployment (Quickstart)\n\nThe fastest way to get up and running is with Docker:\n\n```bash\ndocker run -d --restart=unless-stopped \\\n -p 80:80 -p 443:443 \\\n --privileged \\\n rancher/rancher:latest\n```\n\nThat's it! Navigate to `https://your-server-ip` and you'll be prompted to set a password and server URL.\n\nBut while this method is quick, I prefer the next approach for a more production-like setup.\n\n### Option 2: Installing Rancher on K3s\n\nMy preferred method is to run Rancher on a lightweight Kubernetes distribution like K3s. This gives you better reliability and easier upgrades.\n\nFirst, install K3s:\n\n```bash\ncurl -sfL https://get.k3s.io | sh -\n```\n\nNext, install cert-manager (required for Rancher to manage certificates):\n\n```bash\nkubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.12.2/cert-manager.yaml\n```\n\nThen, install Rancher using Helm:\n\n```bash\nhelm repo add rancher-stable https://releases.rancher.com/server-charts/stable\nhelm repo update\n\nkubectl create namespace cattle-system\n\nhelm install rancher rancher-stable/rancher \\\n --namespace cattle-system \\\n --set hostname=rancher.yourdomain.com \\\n --set bootstrapPassword=admin\n```\n\nDepending on your home lab setup, you might want to use a load balancer or ingress controller. I use Traefik, which comes pre-installed with K3s:\n\n```yaml\napiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n name: rancher\n namespace: cattle-system\nspec:\n rules:\n - host: rancher.yourdomain.com\n http:\n paths:\n - path: /\n pathType: Prefix\n backend:\n service:\n name: rancher\n port:\n number: 80\n tls:\n - hosts:\n - rancher.yourdomain.com\n secretName: rancher-tls\n```\n\n## Importing Your Existing Clusters\n\nOnce Rancher is running, you can import your existing Kubernetes clusters. This is my favorite part because it doesn't require you to rebuild anything.\n\n1. In the Rancher UI, go to \"Cluster Management\"\n2. Click \"Import Existing\"\n3. Choose a name for your cluster\n4. Copy the provided kubectl command and run it on your existing cluster\n\nRancher will install its agent on your cluster and begin managing it. Magic!\n\n## Setting Up Monitoring\n\nRancher makes it dead simple to deploy Prometheus and Grafana for monitoring:\n\n1. From your cluster's dashboard, go to \"Apps\"\n2. Select \"Monitoring\" from the Charts\n3. Install with default settings (or customize as needed)\n\nIn minutes, you'll have a full monitoring stack with pre-configured dashboards for nodes, pods, workloads, and more.\n\nHere's what my Grafana dashboard looks like for my home K8s cluster:\n\n![Rancher Grafana Dashboard](/blog/images/services/rancher-monitoring.jpg)\n\n## Creating Deployments Through the UI\n\nWhile I'm a big fan of GitOps and declarative deployments, sometimes you just want to quickly spin up a container without writing YAML. Rancher makes this painless:\n\n1. Go to your cluster\n2. Select \"Workload > Deployments\"\n3. Click \"Create\"\n4. Fill in the form with your container details\n\nYou get a nice UI for setting environment variables, volumes, health checks, and more. Once you're happy with it, Rancher generates and applies the YAML behind the scenes.\n\n## Rancher Fleet for GitOps\n\nOne of the newer features I love is Fleet, Rancher's GitOps engine. It allows you to manage deployments across clusters using Git repositories:\n\n```yaml\n# Example fleet.yaml\ndefaultNamespace: monitoring\nhelm:\n releaseName: prometheus\n repo: https://prometheus-community.github.io/helm-charts\n chart: kube-prometheus-stack\n version: 39.4.0\n values:\n grafana:\n adminPassword: ${GRAFANA_PASSWORD}\ntargets:\n - name: prod\n clusterSelector:\n matchLabels:\n environment: production\n - name: dev\n clusterSelector:\n matchLabels:\n environment: development\n helm:\n values:\n resources:\n limits:\n memory: 1Gi\n requests:\n memory: 512Mi\n```\n\nWith Fleet, I maintain a Git repository with all my deployments, and Rancher automatically applies them to the appropriate clusters. When I push changes, they're automatically deployed - proper GitOps!\n\n## Rancher for Projects and Teams\n\nIf you're working with a team or want to compartmentalize your applications, Rancher's projects feature is fantastic:\n\n1. Create different projects within a cluster (e.g., \"Media,\" \"Home Automation,\" \"Development\")\n2. Assign namespaces to projects\n3. Set resource quotas for each project\n4. Create users and assign them to projects with specific permissions\n\nThis way, you can give friends or family members access to specific applications without worrying about them breaking your critical services.\n\n## Advanced: Custom Cluster Templates\n\nAs my home lab grew, I started using Rancher's cluster templates to ensure consistency across my Kubernetes installations:\n\n```yaml\napiVersion: management.cattle.io/v3\nkind: ClusterTemplate\nmetadata:\n name: homelab-standard\nspec:\n displayName: HomeStack Standard\n revisionName: homelab-standard-v1\n members:\n - accessType: owner\n userPrincipalName: user-abc123\n template:\n spec:\n rancherKubernetesEngineConfig:\n services:\n etcd:\n backupConfig:\n enabled: true\n intervalHours: 12\n retention: 6\n kubeApi:\n auditLog:\n enabled: true\n network:\n plugin: canal\n monitoring:\n provider: metrics-server\n addons: |-\n apiVersion: v1\n kind: Namespace\n metadata:\n name: cert-manager\n ---\n apiVersion: v1\n kind: Namespace\n metadata:\n name: ingress-nginx\n```\n\n## My Top Rancher Tips\n\nAfter years of using Rancher, here are my top tips:\n\n1. **Use the Rancher CLI**: For repetitive tasks, the CLI is faster than the UI:\n ```bash\n rancher login https://rancher.yourdomain.com --token token-abc123\n rancher kubectl get nodes\n ```\n\n2. **Set Up External Authentication**: Connect Rancher to your identity provider (I use GitHub):\n ```yaml\n # Sample GitHub auth config\n apiVersion: management.cattle.io/v3\n kind: AuthConfig\n metadata:\n name: github\n type: githubConfig\n properties:\n enabled: true\n clientId: your-github-client-id\n clientSecret: your-github-client-secret\n allowedPrincipals:\n - github_user://your-github-username\n - github_org://your-github-org\n ```\n\n3. **Create Node Templates**: If you're using RKE, save node templates for quick cluster expansion.\n\n4. **Use App Templates**: Save your common applications as templates for quick deployment.\n\n5. **Set Up Alerts**: Configure alerts for node health, pod failures, and resource constraints.\n\n## Dealing with Common Rancher Issues\n\nEven the best tools have their quirks. Here are some issues I've encountered and how I solved them:\n\n### Issue: Rancher UI Becomes Slow\n\nIf your Rancher UI starts lagging, check your browser's local storage. The Rancher UI caches a lot of data, which can build up over time:\n\n```javascript\n// Run this in your browser console while on the Rancher page\nlocalStorage.clear()\n```\n\n### Issue: Certificate Errors After DNS Changes\n\nIf you change your domain or DNS settings, Rancher certificates might need to be regenerated:\n\n```bash\nkubectl -n cattle-system delete secret tls-rancher-ingress\nkubectl -n cattle-system delete secret tls-ca\n```\n\nThen restart the Rancher pods:\n\n```bash\nkubectl -n cattle-system rollout restart deploy/rancher\n```\n\n### Issue: Stuck Cluster Imports\n\nIf a cluster gets stuck during import, clean up the agent resources and try again:\n\n```bash\nkubectl delete clusterrole cattle-admin cluster-owner\nkubectl delete clusterrolebinding cattle-admin-binding cluster-owner\nkubectl delete namespace cattle-system\n```\n\n## The Future of Rancher\n\nWith SUSE's acquisition of Rancher Labs, the future looks bright. The latest Rancher updates have added:\n\n- Better integration with cloud providers\n- Improved security features\n- Enhanced multi-cluster management\n- Lower resource requirements (great for home labs)\n\nMy wish list for future versions includes:\n\n- Native GitOps for everything (not just workloads)\n- Better templating for one-click deployments\n- More pre-configured monitoring dashboards\n\n## Wrapping Up\n\nRancher has transformed how I manage my home Kubernetes clusters. What used to be a complex, time-consuming task is now almost... fun? If you're running Kubernetes at home and haven't tried Rancher yet, you're missing out on one of the best tools in the Kubernetes ecosystem.\n\nSure, you could manage everything with kubectl and YAML files (and I still do that sometimes), but having a well-designed UI for management, monitoring, and troubleshooting saves countless hours and reduces the learning curve for those just getting started with Kubernetes.\n\nAre you using Rancher or another tool to manage your Kubernetes clusters? What's been your experience? Let me know in the comments!\n\n---\n\n_This post was last updated on March 5, 2024 with information about Rancher v2.7 features and Fleet GitOps capabilities._","src/content/blog/rancher-kubernetes-management.md","427402e83b2c637e",{"html":641,"metadata":642},"\u003Cp>I’ve been running Kubernetes at home for years now, and I’ve tried just about every management tool out there. From kubectl and a bunch of YAML files to various dashboards and UIs, I’ve experimented with it all. But the one tool that’s been a constant in my home lab journey is \u003Ca href=\"https://rancher.com/\">Rancher\u003C/a> - a complete container management platform that makes Kubernetes management almost… dare I say it… enjoyable?\u003C/p>\n\u003Cp>Today, I want to walk you through setting up Rancher in your home lab and show you some of the features that have made it indispensable for me.\u003C/p>\n\u003Ch2 id=\"what-is-rancher-and-why-should-you-care\">What is Rancher and Why Should You Care?\u003C/h2>\n\u003Cp>Rancher is an open-source platform for managing Kubernetes clusters. Think of it as mission control for all your container workloads. It gives you:\u003C/p>\n\u003Cul>\n\u003Cli>A unified interface for managing multiple clusters (perfect if you’re running different K8s distros)\u003C/li>\n\u003Cli>Simplified deployment of applications via apps & marketplace\u003C/li>\n\u003Cli>Built-in monitoring, logging, and alerting\u003C/li>\n\u003Cli>User management and role-based access control\u003C/li>\n\u003Cli>A clean, intuitive UI that’s actually useful (rare in the Kubernetes world!)\u003C/li>\n\u003C/ul>\n\u003Cp>If you’re running even a single Kubernetes cluster at home, Rancher can save you countless hours of typing \u003Ccode>kubectl\u003C/code> commands and editing YAML files by hand.\u003C/p>\n\u003Ch2 id=\"setting-up-rancher-in-your-home-lab\">Setting Up Rancher in Your Home Lab\u003C/h2>\n\u003Cp>There are several ways to deploy Rancher, but I’ll focus on two approaches that work well for home labs.\u003C/p>\n\u003Ch3 id=\"option-1-docker-deployment-quickstart\">Option 1: Docker Deployment (Quickstart)\u003C/h3>\n\u003Cp>The fastest way to get up and running is with Docker:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">docker\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> run\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -d\u003C/span>\u003Cspan style=\"color:#BD93F9\"> --restart=unless-stopped\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> -p\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 80:80\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -p\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 443:443\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> --privileged\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> rancher/rancher:latest\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>That’s it! Navigate to \u003Ccode>https://your-server-ip\u003C/code> and you’ll be prompted to set a password and server URL.\u003C/p>\n\u003Cp>But while this method is quick, I prefer the next approach for a more production-like setup.\u003C/p>\n\u003Ch3 id=\"option-2-installing-rancher-on-k3s\">Option 2: Installing Rancher on K3s\u003C/h3>\n\u003Cp>My preferred method is to run Rancher on a lightweight Kubernetes distribution like K3s. This gives you better reliability and easier upgrades.\u003C/p>\n\u003Cp>First, install K3s:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">curl\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -sfL\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> https://get.k3s.io\u003C/span>\u003Cspan style=\"color:#FF79C6\"> |\u003C/span>\u003Cspan style=\"color:#50FA7B\"> sh\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> -\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Next, install cert-manager (required for Rancher to manage certificates):\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">kubectl\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> apply\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -f\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> https://github.com/jetstack/cert-manager/releases/download/v1.12.2/cert-manager.yaml\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Then, install Rancher using Helm:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">helm\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> repo\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> add\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> rancher-stable\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> https://releases.rancher.com/server-charts/stable\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">helm\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> repo\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> update\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">kubectl\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> create\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> namespace\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> cattle-system\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">helm\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> install\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> rancher\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> rancher-stable/rancher\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> --namespace\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> cattle-system\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> --set\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> hostname=rancher.yourdomain.com\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> --set\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> bootstrapPassword=admin\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Depending on your home lab setup, you might want to use a load balancer or ingress controller. I use Traefik, which comes pre-installed with K3s:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">apiVersion\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> networking.k8s.io/v1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">kind\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Ingress\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">metadata\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> rancher\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> namespace\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> cattle-system\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> rules\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> host\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> rancher.yourdomain.com\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> http\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> paths\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> path\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> pathType\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Prefix\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> backend\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> service\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> rancher\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> port\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> number\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 80\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> tls\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> hosts\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> rancher.yourdomain.com\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> secretName\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> rancher-tls\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"importing-your-existing-clusters\">Importing Your Existing Clusters\u003C/h2>\n\u003Cp>Once Rancher is running, you can import your existing Kubernetes clusters. This is my favorite part because it doesn’t require you to rebuild anything.\u003C/p>\n\u003Col>\n\u003Cli>In the Rancher UI, go to “Cluster Management”\u003C/li>\n\u003Cli>Click “Import Existing”\u003C/li>\n\u003Cli>Choose a name for your cluster\u003C/li>\n\u003Cli>Copy the provided kubectl command and run it on your existing cluster\u003C/li>\n\u003C/ol>\n\u003Cp>Rancher will install its agent on your cluster and begin managing it. Magic!\u003C/p>\n\u003Ch2 id=\"setting-up-monitoring\">Setting Up Monitoring\u003C/h2>\n\u003Cp>Rancher makes it dead simple to deploy Prometheus and Grafana for monitoring:\u003C/p>\n\u003Col>\n\u003Cli>From your cluster’s dashboard, go to “Apps”\u003C/li>\n\u003Cli>Select “Monitoring” from the Charts\u003C/li>\n\u003Cli>Install with default settings (or customize as needed)\u003C/li>\n\u003C/ol>\n\u003Cp>In minutes, you’ll have a full monitoring stack with pre-configured dashboards for nodes, pods, workloads, and more.\u003C/p>\n\u003Cp>Here’s what my Grafana dashboard looks like for my home K8s cluster:\u003C/p>\n\u003Cp>\u003Cimg src=\"/blog/images/services/rancher-monitoring.jpg\" alt=\"Rancher Grafana Dashboard\">\u003C/p>\n\u003Ch2 id=\"creating-deployments-through-the-ui\">Creating Deployments Through the UI\u003C/h2>\n\u003Cp>While I’m a big fan of GitOps and declarative deployments, sometimes you just want to quickly spin up a container without writing YAML. Rancher makes this painless:\u003C/p>\n\u003Col>\n\u003Cli>Go to your cluster\u003C/li>\n\u003Cli>Select “Workload > Deployments”\u003C/li>\n\u003Cli>Click “Create”\u003C/li>\n\u003Cli>Fill in the form with your container details\u003C/li>\n\u003C/ol>\n\u003Cp>You get a nice UI for setting environment variables, volumes, health checks, and more. Once you’re happy with it, Rancher generates and applies the YAML behind the scenes.\u003C/p>\n\u003Ch2 id=\"rancher-fleet-for-gitops\">Rancher Fleet for GitOps\u003C/h2>\n\u003Cp>One of the newer features I love is Fleet, Rancher’s GitOps engine. It allows you to manage deployments across clusters using Git repositories:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Example fleet.yaml\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">defaultNamespace\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> monitoring\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">helm\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> releaseName\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> prometheus\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> repo\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> https://prometheus-community.github.io/helm-charts\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> chart\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> kube-prometheus-stack\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> version\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 39.4.0\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> values\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> grafana\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> adminPassword\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ${GRAFANA_PASSWORD}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">targets\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> prod\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> clusterSelector\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> matchLabels\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> environment\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> production\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> dev\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> clusterSelector\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> matchLabels\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> environment\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> development\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> helm\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> values\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> resources\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> limits\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> memory\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 1Gi\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> requests\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> memory\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 512Mi\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>With Fleet, I maintain a Git repository with all my deployments, and Rancher automatically applies them to the appropriate clusters. When I push changes, they’re automatically deployed - proper GitOps!\u003C/p>\n\u003Ch2 id=\"rancher-for-projects-and-teams\">Rancher for Projects and Teams\u003C/h2>\n\u003Cp>If you’re working with a team or want to compartmentalize your applications, Rancher’s projects feature is fantastic:\u003C/p>\n\u003Col>\n\u003Cli>Create different projects within a cluster (e.g., “Media,” “Home Automation,” “Development”)\u003C/li>\n\u003Cli>Assign namespaces to projects\u003C/li>\n\u003Cli>Set resource quotas for each project\u003C/li>\n\u003Cli>Create users and assign them to projects with specific permissions\u003C/li>\n\u003C/ol>\n\u003Cp>This way, you can give friends or family members access to specific applications without worrying about them breaking your critical services.\u003C/p>\n\u003Ch2 id=\"advanced-custom-cluster-templates\">Advanced: Custom Cluster Templates\u003C/h2>\n\u003Cp>As my home lab grew, I started using Rancher’s cluster templates to ensure consistency across my Kubernetes installations:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">apiVersion\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> management.cattle.io/v3\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">kind\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ClusterTemplate\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">metadata\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> homelab-standard\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> displayName\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> HomeStack Standard\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> revisionName\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> homelab-standard-v1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> members\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> accessType\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> owner\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> userPrincipalName\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> user-abc123\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> template\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> rancherKubernetesEngineConfig\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> services\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> etcd\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> backupConfig\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> enabled\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> true\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> intervalHours\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 12\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> retention\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 6\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> kubeApi\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> auditLog\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> enabled\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> true\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> network\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> plugin\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> canal\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> monitoring\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> provider\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> metrics-server\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> addons\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#FF79C6\"> |-\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> apiVersion: v1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> kind: Namespace\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> metadata:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> name: cert-manager\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> ---\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> apiVersion: v1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> kind: Namespace\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> metadata:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> name: ingress-nginx\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"my-top-rancher-tips\">My Top Rancher Tips\u003C/h2>\n\u003Cp>After years of using Rancher, here are my top tips:\u003C/p>\n\u003Col>\n\u003Cli>\n\u003Cp>\u003Cstrong>Use the Rancher CLI\u003C/strong>: For repetitive tasks, the CLI is faster than the UI:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">rancher\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> login\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> https://rancher.yourdomain.com\u003C/span>\u003Cspan style=\"color:#BD93F9\"> --token\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> token-abc123\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">rancher\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> kubectl\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> get\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> nodes\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>Set Up External Authentication\u003C/strong>: Connect Rancher to your identity provider (I use GitHub):\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Sample GitHub auth config\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">apiVersion\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> management.cattle.io/v3\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">kind\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> AuthConfig\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">metadata\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> github\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">type\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> githubConfig\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">properties\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> enabled\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> true\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> clientId\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> your-github-client-id\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> clientSecret\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> your-github-client-secret\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> allowedPrincipals\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> github_user://your-github-username\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> github_org://your-github-org\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>Create Node Templates\u003C/strong>: If you’re using RKE, save node templates for quick cluster expansion.\u003C/p>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>Use App Templates\u003C/strong>: Save your common applications as templates for quick deployment.\u003C/p>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>Set Up Alerts\u003C/strong>: Configure alerts for node health, pod failures, and resource constraints.\u003C/p>\n\u003C/li>\n\u003C/ol>\n\u003Ch2 id=\"dealing-with-common-rancher-issues\">Dealing with Common Rancher Issues\u003C/h2>\n\u003Cp>Even the best tools have their quirks. Here are some issues I’ve encountered and how I solved them:\u003C/p>\n\u003Ch3 id=\"issue-rancher-ui-becomes-slow\">Issue: Rancher UI Becomes Slow\u003C/h3>\n\u003Cp>If your Rancher UI starts lagging, check your browser’s local storage. The Rancher UI caches a lot of data, which can build up over time:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"javascript\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\">// Run this in your browser console while on the Rancher page\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">localStorage.\u003C/span>\u003Cspan style=\"color:#50FA7B\">clear\u003C/span>\u003Cspan style=\"color:#F8F8F2\">()\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"issue-certificate-errors-after-dns-changes\">Issue: Certificate Errors After DNS Changes\u003C/h3>\n\u003Cp>If you change your domain or DNS settings, Rancher certificates might need to be regenerated:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">kubectl\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -n\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> cattle-system\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> delete\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> secret\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> tls-rancher-ingress\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">kubectl\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -n\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> cattle-system\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> delete\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> secret\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> tls-ca\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Then restart the Rancher pods:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">kubectl\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -n\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> cattle-system\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> rollout\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> restart\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> deploy/rancher\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"issue-stuck-cluster-imports\">Issue: Stuck Cluster Imports\u003C/h3>\n\u003Cp>If a cluster gets stuck during import, clean up the agent resources and try again:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">kubectl\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> delete\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> clusterrole\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> cattle-admin\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> cluster-owner\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">kubectl\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> delete\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> clusterrolebinding\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> cattle-admin-binding\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> cluster-owner\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">kubectl\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> delete\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> namespace\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> cattle-system\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"the-future-of-rancher\">The Future of Rancher\u003C/h2>\n\u003Cp>With SUSE’s acquisition of Rancher Labs, the future looks bright. The latest Rancher updates have added:\u003C/p>\n\u003Cul>\n\u003Cli>Better integration with cloud providers\u003C/li>\n\u003Cli>Improved security features\u003C/li>\n\u003Cli>Enhanced multi-cluster management\u003C/li>\n\u003Cli>Lower resource requirements (great for home labs)\u003C/li>\n\u003C/ul>\n\u003Cp>My wish list for future versions includes:\u003C/p>\n\u003Cul>\n\u003Cli>Native GitOps for everything (not just workloads)\u003C/li>\n\u003Cli>Better templating for one-click deployments\u003C/li>\n\u003Cli>More pre-configured monitoring dashboards\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"wrapping-up\">Wrapping Up\u003C/h2>\n\u003Cp>Rancher has transformed how I manage my home Kubernetes clusters. What used to be a complex, time-consuming task is now almost… fun? If you’re running Kubernetes at home and haven’t tried Rancher yet, you’re missing out on one of the best tools in the Kubernetes ecosystem.\u003C/p>\n\u003Cp>Sure, you could manage everything with kubectl and YAML files (and I still do that sometimes), but having a well-designed UI for management, monitoring, and troubleshooting saves countless hours and reduces the learning curve for those just getting started with Kubernetes.\u003C/p>\n\u003Cp>Are you using Rancher or another tool to manage your Kubernetes clusters? What’s been your experience? Let me know in the comments!\u003C/p>\n\u003Chr>\n\u003Cp>\u003Cem>This post was last updated on March 5, 2024 with information about Rancher v2.7 features and Fleet GitOps capabilities.\u003C/em>\u003C/p>",{"headings":643,"localImagePaths":693,"remoteImagePaths":694,"frontmatter":695,"imagePaths":699},[644,647,650,653,656,659,662,665,668,671,674,677,680,683,686,689,692],{"depth":55,"slug":645,"text":646},"what-is-rancher-and-why-should-you-care","What is Rancher and Why Should You Care?",{"depth":55,"slug":648,"text":649},"setting-up-rancher-in-your-home-lab","Setting Up Rancher in Your Home Lab",{"depth":97,"slug":651,"text":652},"option-1-docker-deployment-quickstart","Option 1: Docker Deployment (Quickstart)",{"depth":97,"slug":654,"text":655},"option-2-installing-rancher-on-k3s","Option 2: Installing Rancher on K3s",{"depth":55,"slug":657,"text":658},"importing-your-existing-clusters","Importing Your Existing Clusters",{"depth":55,"slug":660,"text":661},"setting-up-monitoring","Setting Up Monitoring",{"depth":55,"slug":663,"text":664},"creating-deployments-through-the-ui","Creating Deployments Through the UI",{"depth":55,"slug":666,"text":667},"rancher-fleet-for-gitops","Rancher Fleet for GitOps",{"depth":55,"slug":669,"text":670},"rancher-for-projects-and-teams","Rancher for Projects and Teams",{"depth":55,"slug":672,"text":673},"advanced-custom-cluster-templates","Advanced: Custom Cluster Templates",{"depth":55,"slug":675,"text":676},"my-top-rancher-tips","My Top Rancher Tips",{"depth":55,"slug":678,"text":679},"dealing-with-common-rancher-issues","Dealing with Common Rancher Issues",{"depth":97,"slug":681,"text":682},"issue-rancher-ui-becomes-slow","Issue: Rancher UI Becomes Slow",{"depth":97,"slug":684,"text":685},"issue-certificate-errors-after-dns-changes","Issue: Certificate Errors After DNS Changes",{"depth":97,"slug":687,"text":688},"issue-stuck-cluster-imports","Issue: Stuck Cluster Imports",{"depth":55,"slug":690,"text":691},"the-future-of-rancher","The Future of Rancher",{"depth":55,"slug":563,"text":564},[],[],{"title":630,"description":631,"pubDate":696,"updatedDate":697,"category":507,"tags":698,"heroImage":17},["Date","2025-04-19T00:00:00.000Z"],["Date","2025-04-18T00:00:00.000Z"],[635,180,181,266,636],[],"rancher-kubernetes-management.md","vscode-server-remote-development",{"id":701,"data":703,"body":712,"filePath":713,"digest":714,"rendered":715,"legacyId":817},{"title":704,"description":705,"pubDate":706,"updatedDate":707,"heroImage":17,"category":507,"tags":708},"Setting Up VS Code Server for Remote Development Anywhere","How to set up and configure VS Code Server for seamless remote development from any device",["Date","2023-04-18T00:00:00.000Z"],["Date","2024-04-19T00:00:00.000Z"],[709,710,511,711,22],"vscode","remote-development","coding","If you're like me, you probably find yourself coding on multiple devices - maybe a desktop at home, a laptop when traveling, or even occasionally on a tablet. For years, keeping development environments in sync was a pain point. Enter [VS Code Server](https://code.visualstudio.com/docs/remote/vscode-server), the solution that has completely transformed my development workflow.\n\nToday, I want to show you how to set up your own self-hosted VS Code Server that lets you code from literally any device with a web browser, all while using your powerful home server for the heavy lifting.\n\n## Why VS Code Server?\n\nBefore we dive into the setup, let's talk about why you might want this:\n\n- **Consistent environment**: The same development setup, extensions, and configurations regardless of which device you're using.\n- **Resource optimization**: Run resource-intensive tasks (builds, tests) on your powerful server instead of your laptop.\n- **Work from anywhere**: Access your development environment from any device with a browser, even an iPad or a borrowed computer.\n- **Seamless switching**: Start working on one device and continue on another without missing a beat.\n\nI've been using this setup for months now, and it's been a game-changer for my productivity. Let's get into the setup!\n\n## Setting Up VS Code Server\n\nThere are a few ways to run VS Code Server. I'll cover the official method and my preferred Docker approach.\n\n### Option 1: Official CLI Installation\n\nThe VS Code team provides a CLI for setting up the server:\n\n```bash\n# Download and install the CLI\ncurl -fsSL https://code.visualstudio.com/sha/download?build=stable&os=cli-alpine-x64 -o vscode_cli.tar.gz\ntar -xf vscode_cli.tar.gz\nsudo mv code /usr/local/bin/\n\n# Start the server\ncode serve-web --accept-server-license-terms --host 0.0.0.0\n```\n\nThis method is straightforward but requires you to manage the process yourself.\n\n### Option 2: Docker Installation (My Preference)\n\nI prefer using Docker for easier updates and management. Here's my `docker-compose.yml`:\n\n```yaml\nversion: '3'\nservices:\n code-server:\n image: linuxserver/code-server:latest\n container_name: code-server\n environment:\n - PUID=1000\n - PGID=1000\n - TZ=America/Los_Angeles\n - PASSWORD=your_secure_password # Consider using Docker secrets instead\n - SUDO_PASSWORD=your_sudo_password # Optional\n - PROXY_DOMAIN=code.yourdomain.com # Optional\n volumes:\n - ./config:/config\n - /path/to/your/projects:/projects\n - /path/to/your/home:/home/coder\n ports:\n - 8443:8443\n restart: unless-stopped\n```\n\nRun it with:\n\n```bash\ndocker-compose up -d\n```\n\nYour VS Code Server will be available at `https://your-server-ip:8443`.\n\n### Option 3: Kubernetes Deployment\n\nFor those running Kubernetes (like me), here's a YAML manifest:\n\n```yaml\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: vscode-server\n namespace: development\nspec:\n replicas: 1\n selector:\n matchLabels:\n app: vscode-server\n template:\n metadata:\n labels:\n app: vscode-server\n spec:\n containers:\n - name: vscode-server\n image: linuxserver/code-server:latest\n env:\n - name: PUID\n value: \"1000\"\n - name: PGID\n value: \"1000\"\n - name: TZ\n value: \"America/Los_Angeles\"\n - name: PASSWORD\n valueFrom:\n secretKeyRef:\n name: vscode-secrets\n key: password\n ports:\n - containerPort: 8443\n volumeMounts:\n - name: config\n mountPath: /config\n - name: projects\n mountPath: /projects\n volumes:\n - name: config\n persistentVolumeClaim:\n claimName: vscode-config\n - name: projects\n persistentVolumeClaim:\n claimName: vscode-projects\n---\napiVersion: v1\nkind: Service\nmetadata:\n name: vscode-server\n namespace: development\nspec:\n selector:\n app: vscode-server\n ports:\n - port: 8443\n targetPort: 8443\n type: ClusterIP\n---\napiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n name: vscode-server\n namespace: development\n annotations:\n kubernetes.io/ingress.class: nginx\n cert-manager.io/cluster-issuer: letsencrypt-prod\nspec:\n tls:\n - hosts:\n - code.yourdomain.com\n secretName: vscode-tls\n rules:\n - host: code.yourdomain.com\n http:\n paths:\n - path: /\n pathType: Prefix\n backend:\n service:\n name: vscode-server\n port:\n number: 8443\n```\n\n## Accessing VS Code Server Securely\n\nYou don't want to expose your development environment directly to the internet without proper security. Here are my recommendations:\n\n### 1. Use a Reverse Proxy with SSL\n\nI use Traefik as a reverse proxy with automatic SSL certificate generation:\n\n```yaml\n# traefik.yml dynamic config\nhttp:\n routers:\n vscode:\n rule: \"Host(`code.yourdomain.com`)\"\n service: \"vscode\"\n entryPoints:\n - websecure\n tls:\n certResolver: letsencrypt\n services:\n vscode:\n loadBalancer:\n servers:\n - url: \"http://localhost:8443\"\n```\n\n### 2. Set Up Authentication\n\nThe LinuxServer image already includes basic authentication, but you can add another layer with something like Authelia:\n\n```yaml\n# authelia configuration.yml\naccess_control:\n default_policy: deny\n rules:\n - domain: code.yourdomain.com\n policy: two_factor\n subject: \"group:developers\"\n```\n\n### 3. Use Cloudflare Tunnel\n\nFor ultimate security, I use a Cloudflare Tunnel to avoid exposing any ports:\n\n```yaml\n# cloudflared config.yml\ntunnel: your-tunnel-id\ncredentials-file: /etc/cloudflared/creds.json\n\ningress:\n - hostname: code.yourdomain.com\n service: http://localhost:8443\n originRequest:\n noTLSVerify: true\n - service: http_status:404\n```\n\n## Configuring Your VS Code Server Environment\n\nOnce your server is running, it's time to set it up for optimal productivity:\n\n### 1. Install Essential Extensions\n\nHere are the must-have extensions I install first:\n\n```bash\n# From the VS Code terminal\ncode-server --install-extension ms-python.python\ncode-server --install-extension ms-azuretools.vscode-docker\ncode-server --install-extension dbaeumer.vscode-eslint\ncode-server --install-extension esbenp.prettier-vscode\ncode-server --install-extension github.copilot\ncode-server --install-extension golang.go\n```\n\nOr you can install them through the Extensions marketplace in the UI.\n\n### 2. Configure Settings Sync\n\nTo keep your settings in sync between instances:\n\n1. Open the Command Palette (Ctrl+Shift+P)\n2. Search for \"Settings Sync: Turn On\"\n3. Sign in with your GitHub or Microsoft account\n\n### 3. Set Up Git Authentication\n\nFor seamless Git operations:\n\n```bash\n# Generate a new SSH key if needed\nssh-keygen -t ed25519 -C \"your_email@example.com\"\n\n# Add to your GitHub/GitLab account\ncat ~/.ssh/id_ed25519.pub\n\n# Configure Git\ngit config --global user.name \"Your Name\"\ngit config --global user.email \"your_email@example.com\"\n```\n\n## Power User Features\n\nNow let's look at some advanced configurations that make VS Code Server even more powerful:\n\n### 1. Workspace Launcher\n\nI created a simple HTML page that lists all my projects for quick access:\n\n```html\n\u003C!DOCTYPE html>\n\u003Chtml>\n\u003Chead>\n \u003Ctitle>LaForceIT Workspace Launcher\u003C/title>\n \u003Cstyle>\n body {\n font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n background-color: #1e1e1e;\n color: #d4d4d4;\n max-width: 800px;\n margin: 0 auto;\n padding: 20px;\n }\n .project-list {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));\n gap: 15px;\n margin-top: 20px;\n }\n .project-card {\n background-color: #252526;\n border-radius: 5px;\n padding: 15px;\n transition: transform 0.2s;\n }\n .project-card:hover {\n transform: translateY(-5px);\n background-color: #2d2d2d;\n }\n a {\n color: #569cd6;\n text-decoration: none;\n }\n h1 { color: #569cd6; }\n h2 { color: #4ec9b0; }\n \u003C/style>\n\u003C/head>\n\u003Cbody>\n \u003Ch1>LaForceIT Workspace Launcher\u003C/h1>\n \u003Cdiv class=\"project-list\">\n \u003Cdiv class=\"project-card\">\n \u003Ch2>ArgoBox\u003C/h2>\n \u003Cp>My Kubernetes home lab platform\u003C/p>\n \u003Ca href=\"/projects/argobox\">Open Workspace\u003C/a>\n \u003C/div>\n \u003Cdiv class=\"project-card\">\n \u003Ch2>Blog\u003C/h2>\n \u003Cp>LaForceIT blog and digital garden\u003C/p>\n \u003Ca href=\"/projects/blog\">Open Workspace\u003C/a>\n \u003C/div>\n \u003C!-- Add more projects as needed -->\n \u003C/div>\n\u003C/body>\n\u003C/html>\n```\n\n### 2. Custom Terminal Profile\n\nAdd this to your `settings.json` for a better terminal experience:\n\n```json\n\"terminal.integrated.profiles.linux\": {\n \"bash\": {\n \"path\": \"bash\",\n \"icon\": \"terminal-bash\",\n \"args\": [\"-l\"]\n },\n \"zsh\": {\n \"path\": \"zsh\"\n },\n \"customProfile\": {\n \"path\": \"bash\",\n \"args\": [\"-c\", \"neofetch && bash -l\"],\n \"icon\": \"terminal-bash\",\n \"overrideName\": true\n }\n},\n\"terminal.integrated.defaultProfile.linux\": \"customProfile\"\n```\n\n### 3. Persistent Development Containers\n\nI use Docker-in-Docker to enable VS Code Dev Containers:\n\n```yaml\nversion: '3'\nservices:\n code-server:\n # ... other config from above\n volumes:\n # ... other volumes\n - /var/run/docker.sock:/var/run/docker.sock\n environment:\n # ... other env vars\n - DOCKER_HOST=unix:///var/run/docker.sock\n```\n\n## Real-World Examples: How I Use VS Code Server\n\nLet me share a few real-world examples of how I use this setup:\n\n### Example 1: Coding on iPad During Travel\n\nWhen traveling with just my iPad, I connect to my VS Code Server to work on my projects. With a Bluetooth keyboard and the amazing iPad screen, it's a surprisingly good experience. The heavy compilation happens on my server back home, so battery life on the iPad remains excellent.\n\n### Example 2: Pair Programming Sessions\n\nWhen helping friends debug issues, I can generate a temporary access link to my VS Code Server:\n\n```bash\n# Create a time-limited token\nTEMP_TOKEN=$(openssl rand -hex 16)\necho \"Token: $TEMP_TOKEN\" > /tmp/temp_token\ncurl -X POST -H \"Content-Type: application/json\" \\\n -d \"{\\\"token\\\":\\\"$TEMP_TOKEN\\\", \\\"expiresIn\\\":\\\"2h\\\"}\" \\\n http://localhost:8443/api/auth/temporary\n```\n\n### Example 3: Switching Between Devices\n\nI often start coding on my desktop, then switch to my laptop when moving to another room. With VS Code Server, I just close the browser on one device and open it on another - my entire session, including unsaved changes and terminal state, remains intact.\n\n## Monitoring and Maintaining Your VS Code Server\n\nTo keep your server running smoothly:\n\n### 1. Set Up Health Checks\n\nI use Uptime Kuma to monitor my VS Code Server:\n\n```yaml\n# Docker Compose snippet for Uptime Kuma\nuptime-kuma:\n image: louislam/uptime-kuma:latest\n container_name: uptime-kuma\n volumes:\n - ./uptime-kuma:/app/data\n ports:\n - 3001:3001\n restart: unless-stopped\n```\n\nAdd a monitor that checks `https://code.yourdomain.com/healthz` endpoint.\n\n### 2. Regular Backups\n\nSet up a cron job to back up your VS Code Server configuration:\n\n```bash\n# /etc/cron.daily/backup-vscode-server\n#!/bin/bash\ntar -czf /backups/vscode-server-$(date +%Y%m%d).tar.gz /path/to/config\n```\n\n### 3. Update Script\n\nCreate a script for easy updates:\n\n```bash\n#!/bin/bash\n# update-vscode-server.sh\ncd /path/to/docker-compose\ndocker-compose pull\ndocker-compose up -d\ndocker system prune -f\n```\n\n## Troubleshooting Common Issues\n\nHere are solutions to some issues I've encountered:\n\n### Issue: Extensions Not Installing\n\nIf extensions fail to install, try:\n\n```bash\n# Clear the extensions cache\nrm -rf ~/.vscode-server/extensions/*\n\n# Restart the server\ndocker-compose restart code-server\n```\n\n### Issue: Performance Problems\n\nIf you're experiencing lag:\n\n```bash\n# Adjust memory limits in docker-compose.yml\nservices:\n code-server:\n # ... other config\n deploy:\n resources:\n limits:\n memory: 4G\n reservations:\n memory: 1G\n```\n\n### Issue: Git Integration Not Working\n\nFor Git authentication issues:\n\n```bash\n# Make sure your SSH key is properly set up\neval \"$(ssh-agent -s)\"\nssh-add ~/.ssh/id_ed25519\n\n# Test your connection\nssh -T git@github.com\n```\n\n## Why I Prefer Self-Hosted Over GitHub Codespaces\n\nPeople often ask why I don't just use GitHub Codespaces. Here's my take:\n\n1. **Cost**: Self-hosted is essentially free (if you already have a server).\n2. **Privacy**: All my code remains on my hardware.\n3. **Customization**: Complete control over the environment.\n4. **Performance**: My server has 64GB RAM and a 12-core CPU - better than most cloud options.\n5. **Availability**: Works even when GitHub is down or when I have limited internet.\n\n## Wrapping Up\n\nVS Code Server has truly changed how I approach development. The ability to have a consistent, powerful environment available from any device has increased my productivity and eliminated the friction of context-switching between machines.\n\nWhether you're a solo developer or part of a team, having a centralized development environment that's accessible from anywhere is incredibly powerful. And the best part? It uses the familiar VS Code interface that millions of developers already know and love.\n\nHave you tried VS Code Server or similar remote development solutions? I'd love to hear about your setup and experiences in the comments!\n\n---\n\n_This post was last updated on March 10, 2024 with information about the latest VS Code Server features and Docker image updates._","src/content/blog/vscode-server-remote-development.md","c0679001dba956e5",{"html":716,"metadata":717},"\u003Cp>If you’re like me, you probably find yourself coding on multiple devices - maybe a desktop at home, a laptop when traveling, or even occasionally on a tablet. For years, keeping development environments in sync was a pain point. Enter \u003Ca href=\"https://code.visualstudio.com/docs/remote/vscode-server\">VS Code Server\u003C/a>, the solution that has completely transformed my development workflow.\u003C/p>\n\u003Cp>Today, I want to show you how to set up your own self-hosted VS Code Server that lets you code from literally any device with a web browser, all while using your powerful home server for the heavy lifting.\u003C/p>\n\u003Ch2 id=\"why-vs-code-server\">Why VS Code Server?\u003C/h2>\n\u003Cp>Before we dive into the setup, let’s talk about why you might want this:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Cstrong>Consistent environment\u003C/strong>: The same development setup, extensions, and configurations regardless of which device you’re using.\u003C/li>\n\u003Cli>\u003Cstrong>Resource optimization\u003C/strong>: Run resource-intensive tasks (builds, tests) on your powerful server instead of your laptop.\u003C/li>\n\u003Cli>\u003Cstrong>Work from anywhere\u003C/strong>: Access your development environment from any device with a browser, even an iPad or a borrowed computer.\u003C/li>\n\u003Cli>\u003Cstrong>Seamless switching\u003C/strong>: Start working on one device and continue on another without missing a beat.\u003C/li>\n\u003C/ul>\n\u003Cp>I’ve been using this setup for months now, and it’s been a game-changer for my productivity. Let’s get into the setup!\u003C/p>\n\u003Ch2 id=\"setting-up-vs-code-server\">Setting Up VS Code Server\u003C/h2>\n\u003Cp>There are a few ways to run VS Code Server. I’ll cover the official method and my preferred Docker approach.\u003C/p>\n\u003Ch3 id=\"option-1-official-cli-installation\">Option 1: Official CLI Installation\u003C/h3>\n\u003Cp>The VS Code team provides a CLI for setting up the server:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Download and install the CLI\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">curl\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -fsSL\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> https://code.visualstudio.com/sha/download?build=stable\u003C/span>\u003Cspan style=\"color:#F8F8F2\">&\u003C/span>\u003Cspan style=\"color:#BD93F9\">os\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#F1FA8C\">cli-alpine-x64\u003C/span>\u003Cspan style=\"color:#50FA7B\"> -o\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> vscode_cli.tar.gz\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">tar\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -xf\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> vscode_cli.tar.gz\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">sudo\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> mv\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> code\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /usr/local/bin/\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Start the server\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">code\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> serve-web\u003C/span>\u003Cspan style=\"color:#BD93F9\"> --accept-server-license-terms\u003C/span>\u003Cspan style=\"color:#BD93F9\"> --host\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 0.0.0.0\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>This method is straightforward but requires you to manage the process yourself.\u003C/p>\n\u003Ch3 id=\"option-2-docker-installation-my-preference\">Option 2: Docker Installation (My Preference)\u003C/h3>\n\u003Cp>I prefer using Docker for easier updates and management. Here’s my \u003Ccode>docker-compose.yml\u003C/code>:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">version\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> '\u003C/span>\u003Cspan style=\"color:#F1FA8C\">3\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">services\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> code-server\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> image\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> linuxserver/code-server:latest\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> container_name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> code-server\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> environment\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> PUID=1000\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> PGID=1000\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> TZ=America/Los_Angeles\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> PASSWORD=your_secure_password\u003C/span>\u003Cspan style=\"color:#6272A4\"> # Consider using Docker secrets instead\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> SUDO_PASSWORD=your_sudo_password\u003C/span>\u003Cspan style=\"color:#6272A4\"> # Optional\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> PROXY_DOMAIN=code.yourdomain.com\u003C/span>\u003Cspan style=\"color:#6272A4\"> # Optional\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> volumes\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ./config:/config\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /path/to/your/projects:/projects\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /path/to/your/home:/home/coder\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> ports\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 8443:8443\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> restart\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> unless-stopped\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Run it with:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">docker-compose\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> up\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -d\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Your VS Code Server will be available at \u003Ccode>https://your-server-ip:8443\u003C/code>.\u003C/p>\n\u003Ch3 id=\"option-3-kubernetes-deployment\">Option 3: Kubernetes Deployment\u003C/h3>\n\u003Cp>For those running Kubernetes (like me), here’s a YAML manifest:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">apiVersion\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> apps/v1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">kind\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Deployment\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">metadata\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> vscode-server\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> namespace\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> development\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> replicas\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> selector\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> matchLabels\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> app\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> vscode-server\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> template\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> metadata\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> labels\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> app\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> vscode-server\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> containers\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> vscode-server\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> image\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> linuxserver/code-server:latest\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> env\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> PUID\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> value\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">1000\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> PGID\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> value\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">1000\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> TZ\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> value\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">America/Los_Angeles\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> PASSWORD\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> valueFrom\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> secretKeyRef\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> vscode-secrets\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> key\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> password\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> ports\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> containerPort\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 8443\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> volumeMounts\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> config\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> mountPath\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /config\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> projects\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> mountPath\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /projects\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> volumes\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> config\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> persistentVolumeClaim\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> claimName\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> vscode-config\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> projects\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> persistentVolumeClaim\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> claimName\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> vscode-projects\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">---\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">apiVersion\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> v1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">kind\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Service\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">metadata\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> vscode-server\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> namespace\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> development\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> selector\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> app\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> vscode-server\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> ports\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> port\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 8443\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> targetPort\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 8443\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> type\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ClusterIP\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">---\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">apiVersion\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> networking.k8s.io/v1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">kind\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Ingress\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">metadata\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> vscode-server\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> namespace\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> development\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> annotations\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> kubernetes.io/ingress.class\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> nginx\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> cert-manager.io/cluster-issuer\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> letsencrypt-prod\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> tls\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> hosts\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> code.yourdomain.com\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> secretName\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> vscode-tls\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> rules\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> host\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> code.yourdomain.com\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> http\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> paths\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> path\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> pathType\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Prefix\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> backend\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> service\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> vscode-server\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> port\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> number\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 8443\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"accessing-vs-code-server-securely\">Accessing VS Code Server Securely\u003C/h2>\n\u003Cp>You don’t want to expose your development environment directly to the internet without proper security. Here are my recommendations:\u003C/p>\n\u003Ch3 id=\"1-use-a-reverse-proxy-with-ssl\">1. Use a Reverse Proxy with SSL\u003C/h3>\n\u003Cp>I use Traefik as a reverse proxy with automatic SSL certificate generation:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># traefik.yml dynamic config\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">http\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> routers\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> vscode\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> rule\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Host(`code.yourdomain.com`)\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> service\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">vscode\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> entryPoints\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> websecure\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> tls\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> certResolver\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> letsencrypt\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> services\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> vscode\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> loadBalancer\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> servers\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> url\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">http://localhost:8443\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"2-set-up-authentication\">2. Set Up Authentication\u003C/h3>\n\u003Cp>The LinuxServer image already includes basic authentication, but you can add another layer with something like Authelia:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># authelia configuration.yml\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">access_control\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> default_policy\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> deny\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> rules\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> domain\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> code.yourdomain.com\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> policy\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> two_factor\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> subject\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">group:developers\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"3-use-cloudflare-tunnel\">3. Use Cloudflare Tunnel\u003C/h3>\n\u003Cp>For ultimate security, I use a Cloudflare Tunnel to avoid exposing any ports:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># cloudflared config.yml\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">tunnel\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> your-tunnel-id\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">credentials-file\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /etc/cloudflared/creds.json\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">ingress\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> hostname\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> code.yourdomain.com\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> service\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> http://localhost:8443\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> originRequest\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> noTLSVerify\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> true\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> service\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> http_status:404\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"configuring-your-vs-code-server-environment\">Configuring Your VS Code Server Environment\u003C/h2>\n\u003Cp>Once your server is running, it’s time to set it up for optimal productivity:\u003C/p>\n\u003Ch3 id=\"1-install-essential-extensions\">1. Install Essential Extensions\u003C/h3>\n\u003Cp>Here are the must-have extensions I install first:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># From the VS Code terminal\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">code-server\u003C/span>\u003Cspan style=\"color:#BD93F9\"> --install-extension\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ms-python.python\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">code-server\u003C/span>\u003Cspan style=\"color:#BD93F9\"> --install-extension\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ms-azuretools.vscode-docker\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">code-server\u003C/span>\u003Cspan style=\"color:#BD93F9\"> --install-extension\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> dbaeumer.vscode-eslint\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">code-server\u003C/span>\u003Cspan style=\"color:#BD93F9\"> --install-extension\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> esbenp.prettier-vscode\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">code-server\u003C/span>\u003Cspan style=\"color:#BD93F9\"> --install-extension\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> github.copilot\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">code-server\u003C/span>\u003Cspan style=\"color:#BD93F9\"> --install-extension\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> golang.go\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Or you can install them through the Extensions marketplace in the UI.\u003C/p>\n\u003Ch3 id=\"2-configure-settings-sync\">2. Configure Settings Sync\u003C/h3>\n\u003Cp>To keep your settings in sync between instances:\u003C/p>\n\u003Col>\n\u003Cli>Open the Command Palette (Ctrl+Shift+P)\u003C/li>\n\u003Cli>Search for “Settings Sync: Turn On”\u003C/li>\n\u003Cli>Sign in with your GitHub or Microsoft account\u003C/li>\n\u003C/ol>\n\u003Ch3 id=\"3-set-up-git-authentication\">3. Set Up Git Authentication\u003C/h3>\n\u003Cp>For seamless Git operations:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Generate a new SSH key if needed\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">ssh-keygen\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -t\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ed25519\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -C\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">your_email@example.com\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Add to your GitHub/GitLab account\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">cat\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ~/.ssh/id_ed25519.pub\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Configure Git\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">git\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> config\u003C/span>\u003Cspan style=\"color:#BD93F9\"> --global\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> user.name\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Your Name\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">git\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> config\u003C/span>\u003Cspan style=\"color:#BD93F9\"> --global\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> user.email\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">your_email@example.com\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"power-user-features\">Power User Features\u003C/h2>\n\u003Cp>Now let’s look at some advanced configurations that make VS Code Server even more powerful:\u003C/p>\n\u003Ch3 id=\"1-workspace-launcher\">1. Workspace Launcher\u003C/h3>\n\u003Cp>I created a simple HTML page that lists all my projects for quick access:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"html\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"><!\u003C/span>\u003Cspan style=\"color:#FF79C6\">DOCTYPE\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\"> html\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"><\u003C/span>\u003Cspan style=\"color:#FF79C6\">html\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"><\u003C/span>\u003Cspan style=\"color:#FF79C6\">head\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> <\u003C/span>\u003Cspan style=\"color:#FF79C6\">title\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>LaForceIT Workspace Launcher</\u003C/span>\u003Cspan style=\"color:#FF79C6\">title\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> <\u003C/span>\u003Cspan style=\"color:#FF79C6\">style\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> body\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> font-family\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> '\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Segoe UI\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#BD93F9\">Tahoma\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, Geneva, \u003C/span>\u003Cspan style=\"color:#BD93F9\">Verdana\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#BD93F9\">sans-serif\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> background-color\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> #1e1e1e\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> color\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> #d4d4d4\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> max-width\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 800\u003C/span>\u003Cspan style=\"color:#FF79C6\">px\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> margin\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 0\u003C/span>\u003Cspan style=\"color:#BD93F9\"> auto\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> padding\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 20\u003C/span>\u003Cspan style=\"color:#FF79C6\">px\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B;font-style:italic\"> .project-list\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> display\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> grid\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> grid-template-columns\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> repeat\u003C/span>\u003Cspan style=\"color:#F8F8F2\">(\u003C/span>\u003Cspan style=\"color:#BD93F9\">auto-fill\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#8BE9FD\">minmax\u003C/span>\u003Cspan style=\"color:#F8F8F2\">(\u003C/span>\u003Cspan style=\"color:#BD93F9\">200\u003C/span>\u003Cspan style=\"color:#FF79C6\">px\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#BD93F9\">1\u003C/span>\u003Cspan style=\"color:#FF79C6\">fr\u003C/span>\u003Cspan style=\"color:#F8F8F2\">));\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> gap\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 15\u003C/span>\u003Cspan style=\"color:#FF79C6\">px\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> margin-top\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 20\u003C/span>\u003Cspan style=\"color:#FF79C6\">px\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B;font-style:italic\"> .project-card\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> background-color\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> #252526\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> border-radius\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 5\u003C/span>\u003Cspan style=\"color:#FF79C6\">px\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> padding\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 15\u003C/span>\u003Cspan style=\"color:#FF79C6\">px\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> transition\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> transform \u003C/span>\u003Cspan style=\"color:#BD93F9\">0.2\u003C/span>\u003Cspan style=\"color:#FF79C6\">s\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B;font-style:italic\"> .project-card\u003C/span>\u003Cspan style=\"color:#FF79C6;font-style:italic\">:\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\">hover\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> transform\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> translateY\u003C/span>\u003Cspan style=\"color:#F8F8F2\">(\u003C/span>\u003Cspan style=\"color:#BD93F9\">-5\u003C/span>\u003Cspan style=\"color:#FF79C6\">px\u003C/span>\u003Cspan style=\"color:#F8F8F2\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> background-color\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> #2d2d2d\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> a\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> color\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> #569cd6\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> text-decoration\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> none\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> h1\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> { \u003C/span>\u003Cspan style=\"color:#8BE9FD\">color\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> #569cd6\u003C/span>\u003Cspan style=\"color:#F8F8F2\">; }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> h2\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> { \u003C/span>\u003Cspan style=\"color:#8BE9FD\">color\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> #4ec9b0\u003C/span>\u003Cspan style=\"color:#F8F8F2\">; }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> </\u003C/span>\u003Cspan style=\"color:#FF79C6\">style\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"></\u003C/span>\u003Cspan style=\"color:#FF79C6\">head\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"><\u003C/span>\u003Cspan style=\"color:#FF79C6\">body\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> <\u003C/span>\u003Cspan style=\"color:#FF79C6\">h1\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>LaForceIT Workspace Launcher</\u003C/span>\u003Cspan style=\"color:#FF79C6\">h1\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> <\u003C/span>\u003Cspan style=\"color:#FF79C6\">div\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\"> class\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">project-list\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> <\u003C/span>\u003Cspan style=\"color:#FF79C6\">div\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\"> class\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">project-card\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> <\u003C/span>\u003Cspan style=\"color:#FF79C6\">h2\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>ArgoBox</\u003C/span>\u003Cspan style=\"color:#FF79C6\">h2\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> <\u003C/span>\u003Cspan style=\"color:#FF79C6\">p\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>My Kubernetes home lab platform</\u003C/span>\u003Cspan style=\"color:#FF79C6\">p\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> <\u003C/span>\u003Cspan style=\"color:#FF79C6\">a\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\"> href\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">/projects/argobox\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>Open Workspace</\u003C/span>\u003Cspan style=\"color:#FF79C6\">a\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> </\u003C/span>\u003Cspan style=\"color:#FF79C6\">div\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> <\u003C/span>\u003Cspan style=\"color:#FF79C6\">div\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\"> class\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">project-card\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> <\u003C/span>\u003Cspan style=\"color:#FF79C6\">h2\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>Blog</\u003C/span>\u003Cspan style=\"color:#FF79C6\">h2\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> <\u003C/span>\u003Cspan style=\"color:#FF79C6\">p\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>LaForceIT blog and digital garden</\u003C/span>\u003Cspan style=\"color:#FF79C6\">p\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> <\u003C/span>\u003Cspan style=\"color:#FF79C6\">a\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\"> href\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">/projects/blog\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>Open Workspace</\u003C/span>\u003Cspan style=\"color:#FF79C6\">a\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> </\u003C/span>\u003Cspan style=\"color:#FF79C6\">div\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> <!-- Add more projects as needed -->\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> </\u003C/span>\u003Cspan style=\"color:#FF79C6\">div\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"></\u003C/span>\u003Cspan style=\"color:#FF79C6\">body\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"></\u003C/span>\u003Cspan style=\"color:#FF79C6\">html\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"2-custom-terminal-profile\">2. Custom Terminal Profile\u003C/h3>\n\u003Cp>Add this to your \u003Ccode>settings.json\u003C/code> for a better terminal experience:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"json\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">terminal.integrated.profiles.linux\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">: {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">bash\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">path\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">bash\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">icon\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">terminal-bash\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">args\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">-l\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">]\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">zsh\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">path\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">zsh\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">customProfile\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">path\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">bash\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">args\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">-c\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">neofetch && bash -l\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">],\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">icon\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">terminal-bash\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">overrideName\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> true\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">},\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">terminal.integrated.defaultProfile.linux\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">: \u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">customProfile\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"3-persistent-development-containers\">3. Persistent Development Containers\u003C/h3>\n\u003Cp>I use Docker-in-Docker to enable VS Code Dev Containers:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">version\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> '\u003C/span>\u003Cspan style=\"color:#F1FA8C\">3\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">services\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> code-server\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> # ... other config from above\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> volumes\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> # ... other volumes\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /var/run/docker.sock:/var/run/docker.sock\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> environment\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> # ... other env vars\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> DOCKER_HOST=unix:///var/run/docker.sock\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"real-world-examples-how-i-use-vs-code-server\">Real-World Examples: How I Use VS Code Server\u003C/h2>\n\u003Cp>Let me share a few real-world examples of how I use this setup:\u003C/p>\n\u003Ch3 id=\"example-1-coding-on-ipad-during-travel\">Example 1: Coding on iPad During Travel\u003C/h3>\n\u003Cp>When traveling with just my iPad, I connect to my VS Code Server to work on my projects. With a Bluetooth keyboard and the amazing iPad screen, it’s a surprisingly good experience. The heavy compilation happens on my server back home, so battery life on the iPad remains excellent.\u003C/p>\n\u003Ch3 id=\"example-2-pair-programming-sessions\">Example 2: Pair Programming Sessions\u003C/h3>\n\u003Cp>When helping friends debug issues, I can generate a temporary access link to my VS Code Server:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Create a time-limited token\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\">TEMP_TOKEN\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#F8F8F2\">$(\u003C/span>\u003Cspan style=\"color:#50FA7B\">openssl\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> rand\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -hex\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 16\u003C/span>\u003Cspan style=\"color:#F8F8F2\">)\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">echo\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Token: \u003C/span>\u003Cspan style=\"color:#BD93F9\">$TEMP_TOKEN\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\"> >\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /tmp/temp_token\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">curl\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -X\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> POST\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -H\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Content-Type: application/json\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> -d\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">{\u003C/span>\u003Cspan style=\"color:#FF79C6\">\\\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">token\u003C/span>\u003Cspan style=\"color:#FF79C6\">\\\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">:\u003C/span>\u003Cspan style=\"color:#FF79C6\">\\\"\u003C/span>\u003Cspan style=\"color:#BD93F9\">$TEMP_TOKEN\u003C/span>\u003Cspan style=\"color:#FF79C6\">\\\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">, \u003C/span>\u003Cspan style=\"color:#FF79C6\">\\\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">expiresIn\u003C/span>\u003Cspan style=\"color:#FF79C6\">\\\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">:\u003C/span>\u003Cspan style=\"color:#FF79C6\">\\\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">2h\u003C/span>\u003Cspan style=\"color:#FF79C6\">\\\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">}\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> http://localhost:8443/api/auth/temporary\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"example-3-switching-between-devices\">Example 3: Switching Between Devices\u003C/h3>\n\u003Cp>I often start coding on my desktop, then switch to my laptop when moving to another room. With VS Code Server, I just close the browser on one device and open it on another - my entire session, including unsaved changes and terminal state, remains intact.\u003C/p>\n\u003Ch2 id=\"monitoring-and-maintaining-your-vs-code-server\">Monitoring and Maintaining Your VS Code Server\u003C/h2>\n\u003Cp>To keep your server running smoothly:\u003C/p>\n\u003Ch3 id=\"1-set-up-health-checks\">1. Set Up Health Checks\u003C/h3>\n\u003Cp>I use Uptime Kuma to monitor my VS Code Server:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Docker Compose snippet for Uptime Kuma\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">uptime-kuma\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> image\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> louislam/uptime-kuma:latest\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> container_name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> uptime-kuma\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> volumes\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ./uptime-kuma:/app/data\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> ports\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 3001:3001\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> restart\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> unless-stopped\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Add a monitor that checks \u003Ccode>https://code.yourdomain.com/healthz\u003C/code> endpoint.\u003C/p>\n\u003Ch3 id=\"2-regular-backups\">2. Regular Backups\u003C/h3>\n\u003Cp>Set up a cron job to back up your VS Code Server configuration:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># /etc/cron.daily/backup-vscode-server\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\">#!/bin/bash\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">tar\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -czf\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /backups/vscode-server-\u003C/span>\u003Cspan style=\"color:#F8F8F2\">$(\u003C/span>\u003Cspan style=\"color:#50FA7B\">date\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> +%Y%m%d\u003C/span>\u003Cspan style=\"color:#F8F8F2\">)\u003C/span>\u003Cspan style=\"color:#F1FA8C\">.tar.gz\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /path/to/config\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"3-update-script\">3. Update Script\u003C/h3>\n\u003Cp>Create a script for easy updates:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\">#!/bin/bash\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># update-vscode-server.sh\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">cd\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /path/to/docker-compose\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">docker-compose\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> pull\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">docker-compose\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> up\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -d\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">docker\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> system\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> prune\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -f\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"troubleshooting-common-issues\">Troubleshooting Common Issues\u003C/h2>\n\u003Cp>Here are solutions to some issues I’ve encountered:\u003C/p>\n\u003Ch3 id=\"issue-extensions-not-installing\">Issue: Extensions Not Installing\u003C/h3>\n\u003Cp>If extensions fail to install, try:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Clear the extensions cache\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">rm\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -rf\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ~/.vscode-server/extensions/\u003C/span>\u003Cspan style=\"color:#BD93F9;font-style:italic\">*\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Restart the server\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">docker-compose\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> restart\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> code-server\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"issue-performance-problems\">Issue: Performance Problems\u003C/h3>\n\u003Cp>If you’re experiencing lag:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Adjust memory limits in docker-compose.yml\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">services:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\"> code-server:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> # ... other config\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\"> deploy:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\"> resources:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\"> limits:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\"> memory:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 4G\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\"> reservations:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\"> memory:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 1G\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"issue-git-integration-not-working\">Issue: Git Integration Not Working\u003C/h3>\n\u003Cp>For Git authentication issues:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Make sure your SSH key is properly set up\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">eval\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">$(\u003C/span>\u003Cspan style=\"color:#50FA7B\">ssh-agent\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -s\u003C/span>\u003Cspan style=\"color:#F1FA8C\">)\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">ssh-add\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ~/.ssh/id_ed25519\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Test your connection\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">ssh\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -T\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> git@github.com\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"why-i-prefer-self-hosted-over-github-codespaces\">Why I Prefer Self-Hosted Over GitHub Codespaces\u003C/h2>\n\u003Cp>People often ask why I don’t just use GitHub Codespaces. Here’s my take:\u003C/p>\n\u003Col>\n\u003Cli>\u003Cstrong>Cost\u003C/strong>: Self-hosted is essentially free (if you already have a server).\u003C/li>\n\u003Cli>\u003Cstrong>Privacy\u003C/strong>: All my code remains on my hardware.\u003C/li>\n\u003Cli>\u003Cstrong>Customization\u003C/strong>: Complete control over the environment.\u003C/li>\n\u003Cli>\u003Cstrong>Performance\u003C/strong>: My server has 64GB RAM and a 12-core CPU - better than most cloud options.\u003C/li>\n\u003Cli>\u003Cstrong>Availability\u003C/strong>: Works even when GitHub is down or when I have limited internet.\u003C/li>\n\u003C/ol>\n\u003Ch2 id=\"wrapping-up\">Wrapping Up\u003C/h2>\n\u003Cp>VS Code Server has truly changed how I approach development. The ability to have a consistent, powerful environment available from any device has increased my productivity and eliminated the friction of context-switching between machines.\u003C/p>\n\u003Cp>Whether you’re a solo developer or part of a team, having a centralized development environment that’s accessible from anywhere is incredibly powerful. And the best part? It uses the familiar VS Code interface that millions of developers already know and love.\u003C/p>\n\u003Cp>Have you tried VS Code Server or similar remote development solutions? I’d love to hear about your setup and experiences in the comments!\u003C/p>\n\u003Chr>\n\u003Cp>\u003Cem>This post was last updated on March 10, 2024 with information about the latest VS Code Server features and Docker image updates.\u003C/em>\u003C/p>",{"headings":718,"localImagePaths":810,"remoteImagePaths":811,"frontmatter":812,"imagePaths":816},[719,722,725,728,731,734,737,740,743,746,749,752,755,758,761,764,767,770,773,776,779,782,785,788,791,794,797,800,803,806,809],{"depth":55,"slug":720,"text":721},"why-vs-code-server","Why VS Code Server?",{"depth":55,"slug":723,"text":724},"setting-up-vs-code-server","Setting Up VS Code Server",{"depth":97,"slug":726,"text":727},"option-1-official-cli-installation","Option 1: Official CLI Installation",{"depth":97,"slug":729,"text":730},"option-2-docker-installation-my-preference","Option 2: Docker Installation (My Preference)",{"depth":97,"slug":732,"text":733},"option-3-kubernetes-deployment","Option 3: Kubernetes Deployment",{"depth":55,"slug":735,"text":736},"accessing-vs-code-server-securely","Accessing VS Code Server Securely",{"depth":97,"slug":738,"text":739},"1-use-a-reverse-proxy-with-ssl","1. Use a Reverse Proxy with SSL",{"depth":97,"slug":741,"text":742},"2-set-up-authentication","2. Set Up Authentication",{"depth":97,"slug":744,"text":745},"3-use-cloudflare-tunnel","3. Use Cloudflare Tunnel",{"depth":55,"slug":747,"text":748},"configuring-your-vs-code-server-environment","Configuring Your VS Code Server Environment",{"depth":97,"slug":750,"text":751},"1-install-essential-extensions","1. Install Essential Extensions",{"depth":97,"slug":753,"text":754},"2-configure-settings-sync","2. Configure Settings Sync",{"depth":97,"slug":756,"text":757},"3-set-up-git-authentication","3. Set Up Git Authentication",{"depth":55,"slug":759,"text":760},"power-user-features","Power User Features",{"depth":97,"slug":762,"text":763},"1-workspace-launcher","1. Workspace Launcher",{"depth":97,"slug":765,"text":766},"2-custom-terminal-profile","2. Custom Terminal Profile",{"depth":97,"slug":768,"text":769},"3-persistent-development-containers","3. Persistent Development Containers",{"depth":55,"slug":771,"text":772},"real-world-examples-how-i-use-vs-code-server","Real-World Examples: How I Use VS Code Server",{"depth":97,"slug":774,"text":775},"example-1-coding-on-ipad-during-travel","Example 1: Coding on iPad During Travel",{"depth":97,"slug":777,"text":778},"example-2-pair-programming-sessions","Example 2: Pair Programming Sessions",{"depth":97,"slug":780,"text":781},"example-3-switching-between-devices","Example 3: Switching Between Devices",{"depth":55,"slug":783,"text":784},"monitoring-and-maintaining-your-vs-code-server","Monitoring and Maintaining Your VS Code Server",{"depth":97,"slug":786,"text":787},"1-set-up-health-checks","1. Set Up Health Checks",{"depth":97,"slug":789,"text":790},"2-regular-backups","2. Regular Backups",{"depth":97,"slug":792,"text":793},"3-update-script","3. Update Script",{"depth":55,"slug":795,"text":796},"troubleshooting-common-issues","Troubleshooting Common Issues",{"depth":97,"slug":798,"text":799},"issue-extensions-not-installing","Issue: Extensions Not Installing",{"depth":97,"slug":801,"text":802},"issue-performance-problems","Issue: Performance Problems",{"depth":97,"slug":804,"text":805},"issue-git-integration-not-working","Issue: Git Integration Not Working",{"depth":55,"slug":807,"text":808},"why-i-prefer-self-hosted-over-github-codespaces","Why I Prefer Self-Hosted Over GitHub Codespaces",{"depth":55,"slug":563,"text":564},[],[],{"title":704,"description":705,"pubDate":813,"updatedDate":814,"category":507,"tags":815,"heroImage":17},["Date","2023-04-18T00:00:00.000Z"],["Date","2024-04-19T00:00:00.000Z"],[709,710,511,711,22],[],"vscode-server-remote-development.md","quartz-digital-garden",{"id":818,"data":820,"body":829,"filePath":830,"digest":831,"rendered":832,"legacyId":890},{"title":821,"description":822,"pubDate":823,"updatedDate":824,"heroImage":17,"category":507,"tags":825},"Building a Digital Garden with Quartz, Obsidian, and Astro","How to transform your Obsidian notes into a beautiful, connected public digital garden using Quartz and Astro",["Date","2025-04-18T00:00:00.000Z"],["Date","2025-04-19T00:00:00.000Z"],[826,827,448,449,828],"quartz","obsidian","astro","I've been taking digital notes for decades now. From simple `.txt` files to OneNote, Evernote, Notion, and now Obsidian. But for years, I've been wrestling with a question: how do I share my knowledge with others in a way that preserves the connections between ideas?\n\nEnter [Quartz](https://quartz.jzhao.xyz/) - an open-source static site generator designed specifically for transforming Obsidian vaults into interconnected digital gardens. I've been using it with Astro to power this very blog, and today I want to show you how you can do the same.\n\n## What is a Digital Garden?\n\nBefore we dive into the technical stuff, let's talk about what a digital garden actually is. Unlike traditional blogs organized chronologically, a digital garden is more like... well, a garden! It's a collection of interconnected notes that grow over time.\n\nThink of each note as a plant. Some are seedlings (early ideas), some are in full bloom (well-developed thoughts), and others might be somewhere in between. The beauty of a digital garden is that it evolves organically, with connections forming between ideas just as they do in our brains.\n\n## Why Quartz + Obsidian + Astro?\n\nI settled on this stack after trying numerous solutions, and here's why:\n\n- **Obsidian**: Provides a fantastic editing experience with bi-directional linking, graph views, and markdown support.\n- **Quartz**: Transforms Obsidian vaults into interconnected websites with minimal configuration.\n- **Astro**: Adds flexibility for custom layouts, components, and integrations not available in Quartz alone.\n\nIt's a match made in heaven - I get the best note-taking experience with Obsidian, the connection-preserving features of Quartz, and the full power of a modern web framework with Astro.\n\n## Setting Up Your Digital Garden\n\nLet's walk through how to set this up step by step.\n\n### Step 1: Install Obsidian and Create a Vault\n\nIf you haven't already, [download Obsidian](https://obsidian.md/) and create a new vault for your digital garden content. I recommend having a separate vault for public content to keep it clean.\n\n### Step 2: Set Up Quartz\n\nQuartz is essentially a template for your Obsidian content. Here's how to get it running:\n\n```bash\n# Clone the Quartz repository\ngit clone https://github.com/jackyzha0/quartz.git\ncd quartz\n\n# Install dependencies\nnpm install\n\n# Copy your Obsidian vault content to the content folder\n# (or symlink it, which is what I do)\nln -s /path/to/your/obsidian/vault content\n```\n\nOnce installed, you can customize your Quartz configuration in the `quartz.config.ts` file. Here's a snippet of mine:\n\n```typescript\n// quartz.config.ts\nconst config: QuartzConfig = {\n configuration: {\n pageTitle: \"LaForceIT Digital Garden\",\n enableSPA: true,\n enablePopovers: true,\n analytics: {\n provider: \"plausible\",\n },\n baseUrl: \"blog.laforceit.com\",\n ignorePatterns: [\"private\", \"templates\", \".obsidian\"],\n theme: {\n typography: {\n header: \"Space Grotesk\",\n body: \"Space Grotesk\",\n code: \"JetBrains Mono\",\n },\n colors: {\n lightMode: {\n light: \"#fafafa\",\n lightgray: \"#e5e5e5\",\n gray: \"#b8b8b8\",\n darkgray: \"#4e4e4e\",\n dark: \"#2b2b2b\",\n secondary: \"#284b63\",\n tertiary: \"#84a59d\",\n highlight: \"rgba(143, 159, 169, 0.15)\",\n },\n darkMode: {\n light: \"#050a18\",\n lightgray: \"#0f172a\",\n gray: \"#1e293b\",\n darkgray: \"#94a3b8\",\n dark: \"#e2e8f0\",\n secondary: \"#06b6d4\",\n tertiary: \"#3b82f6\",\n highlight: \"rgba(6, 182, 212, 0.15)\",\n },\n },\n },\n },\n plugins: {\n transformers: [\n // plugins here\n ],\n filters: [\n // filters here\n ],\n emitters: [\n // emitters here\n ],\n }\n};\n```\n\n### Step 3: Integrating with Astro\n\nNow, where Quartz ends and Astro begins is where the magic really happens. Here's how I integrated them:\n\n1. Create a new Astro project:\n\n```bash\nnpm create astro@latest my-digital-garden\ncd my-digital-garden\n```\n\n2. Set up your Astro project structure:\n\n```\nmy-digital-garden/\n├── public/\n├── src/\n│ ├── components/\n│ ├── layouts/\n│ ├── pages/\n│ │ └── index.astro\n│ └── content/ (this will point to your Quartz content)\n├── astro.config.mjs\n└── package.json\n```\n\n3. Configure Astro to work with Quartz's output:\n\n```typescript\n// astro.config.mjs\nimport { defineConfig } from 'astro/config';\n\nexport default defineConfig({\n integrations: [\n // Your integrations here\n ],\n markdown: {\n remarkPlugins: [\n // The same remark plugins used in Quartz\n ],\n rehypePlugins: [\n // The same rehype plugins used in Quartz\n ]\n }\n});\n```\n\n4. Create a component for the Obsidian graph view (similar to what I use on this blog):\n\n```astro\n---\n// Graph.astro\n---\n\n\u003Cdiv class=\"graph-container\">\n \u003Cdiv class=\"graph-visualization\">\n \u003Cdiv class=\"graph-overlay\">\u003C/div>\n \u003Cdiv class=\"graph-nodes\" id=\"obsidian-graph\">\u003C/div>\n \u003C/div>\n \u003Cdiv class=\"graph-caption\">Interactive visualization of interconnected notes\u003C/div>\n\u003C/div>\n\n\u003Cscript src=\"/blog/scripts/neural-network.js\" defer>\u003C/script>\n\n\u003Cstyle>\n .graph-container {\n width: 100%;\n height: 400px;\n position: relative;\n border-radius: 0.75rem;\n overflow: hidden;\n background: rgba(15, 23, 42, 0.6);\n border: 1px solid rgba(56, 189, 248, 0.2);\n }\n \n .graph-visualization {\n width: 100%;\n height: 100%;\n position: relative;\n }\n \n .graph-overlay {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: radial-gradient(\n circle at center,\n transparent 0%,\n rgba(15, 23, 42, 0.5) 100%\n );\n z-index: 1;\n pointer-events: none;\n }\n \n .graph-nodes {\n width: 100%;\n height: 100%;\n position: relative;\n z-index: 2;\n }\n \n .graph-caption {\n position: absolute;\n bottom: 0.75rem;\n left: 0;\n width: 100%;\n text-align: center;\n color: rgba(148, 163, 184, 0.8);\n font-size: 0.875rem;\n z-index: 3;\n }\n\u003C/style>\n```\n\n## Writing Content for Your Digital Garden\n\nNow that you have the technical setup, let's talk about how to structure your content. Here's how I approach it:\n\n### 1. Use Meaningful Frontmatter\n\nEach note should have frontmatter that helps organize and categorize it:\n\n```markdown\n---\ntitle: \"Building a Digital Garden\"\ndescription: \"How to create a connected knowledge base with Obsidian and Quartz\"\npubDate: 2023-11-05\nupdatedDate: 2024-02-10\ncategory: \"Knowledge Management\"\ntags: [\"digital-garden\", \"obsidian\", \"quartz\", \"notes\"]\n---\n```\n\n### 2. Create Meaningful Connections\n\nThe power of a digital garden comes from connections. Use Obsidian's `[[wiki-links]]` liberally to connect related concepts:\n\n```markdown\nI'm using the [[quartz-digital-garden|Quartz framework]] to power my digital garden. It works well with [[obsidian-setup|my Obsidian workflow]].\n```\n\n### 3. Use Consistent Structure for Your Notes\n\nI follow a template for most of my notes to maintain consistency:\n\n- Brief introduction/definition\n- Why it matters\n- Key concepts\n- Examples or code snippets\n- References to related notes\n- External resources\n\n### 4. Leverage Obsidian Features\n\nMake use of Obsidian's unique features that Quartz preserves:\n\n- **Callouts** for highlighting important information\n- **Dataview** for creating dynamic content (if using the Dataview plugin)\n- **Graphs** to visualize connections\n\n## Deploying Your Digital Garden\n\nHere's how I deploy my digital garden to Cloudflare Pages:\n\n1. **Build Configuration**:\n\n```javascript\n// Build command\nastro build\n\n// Output directory\ndist\n```\n\n2. **Automated Deployment from Git**:\n\nI have a GitHub action that publishes my content whenever I push changes:\n\n```yaml\nname: Deploy to Cloudflare Pages\n\non:\n push:\n branches: [main]\n\njobs:\n deploy:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v3\n with:\n submodules: true\n - uses: actions/setup-node@v3\n with:\n node-version: 18\n - name: Install Dependencies\n run: npm ci\n - name: Build\n run: npm run build\n - name: Deploy to Cloudflare Pages\n uses: cloudflare/pages-action@v1\n with:\n apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}\n accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}\n projectName: digital-garden\n directory: dist\n```\n\n## My Digital Garden Workflow\n\nHere's my actual workflow for maintaining my digital garden:\n\n1. **Daily note-taking** in Obsidian (private vault)\n2. **Weekly review** where I refine notes and connections\n3. **Publishing prep** where I move polished notes to my public vault\n4. **Git commit and push** which triggers the deployment\n\nThe beauty of this system is that my private thinking and public sharing use the same tools and formats, reducing friction between capturing thoughts and sharing them.\n\n## Adding Interactive Elements\n\nOne of my favorite parts of using Astro with Quartz is that I can add interactive elements to my digital garden. For example, the neural graph visualization you see on this blog:\n\n```javascript\n// Simplified version of the neural network graph code\ndocument.addEventListener('DOMContentLoaded', () => {\n const container = document.querySelector('.graph-nodes');\n if (!container) return;\n \n // Configuration\n const CONNECTION_DISTANCE = 30;\n const MIN_NODE_SIZE = 4;\n const MAX_NODE_SIZE = 12;\n \n // Fetch blog data from the same origin\n async function fetchQuartzData() {\n // In production, fetch from your actual API\n return {\n nodes: [\n {\n id: 'digital-garden',\n title: 'Digital Garden',\n tags: ['knowledge-management', 'notes'],\n category: 'concept'\n },\n // More nodes here\n ],\n links: [\n { source: 'digital-garden', target: 'obsidian' },\n // More links here\n ]\n };\n }\n \n // Create the visualization\n fetchQuartzData().then(graphData => {\n // Create nodes and connections\n // (implementation details omitted for brevity)\n });\n});\n```\n\n## Tips for a Successful Digital Garden\n\nAfter maintaining my digital garden for over a year, here are my top tips:\n\n1. **Start small** - Begin with a few well-connected notes rather than trying to publish everything at once.\n\n2. **Focus on connections** - The value is in the links between notes, not just the notes themselves.\n\n3. **Embrace imperfection** - Digital gardens are meant to grow and evolve; they're never \"finished.\"\n\n4. **Build in public** - Share your process and learnings as you go.\n\n5. **Use consistent formatting** - Makes it easier for readers to navigate your garden.\n\n## The Impact of My Digital Garden\n\nSince starting my digital garden, I've experienced several unexpected benefits:\n\n- **Clearer thinking** - Writing for an audience forces me to clarify my thoughts.\n- **Unexpected connections** - I've discovered relationships between ideas I hadn't noticed before.\n- **Community building** - I've connected with others interested in the same topics.\n- **Learning accountability** - Publishing regularly motivates me to keep learning.\n\n## Wrapping Up\n\nBuilding a digital garden with Quartz, Obsidian, and Astro has transformed how I learn and share knowledge. It's become so much more than a blog - it's a living representation of my thinking that grows more valuable with each connection I make.\n\nIf you're considering starting your own digital garden, I hope this guide gives you a solid foundation. Remember, the best garden is the one you actually tend to, so start simple and let it grow naturally over time.\n\nWhat about you? Are you maintaining a digital garden or thinking about starting one? I'd love to hear about your experience in the comments!\n\n---\n\n_This post was last updated on February 10, 2024 with information about the latest Quartz configuration options and integration with Astro._","src/content/blog/quartz-digital-garden.md","2dedac3c8cf5700d",{"html":833,"metadata":834},"\u003Cp>I’ve been taking digital notes for decades now. From simple \u003Ccode>.txt\u003C/code> files to OneNote, Evernote, Notion, and now Obsidian. But for years, I’ve been wrestling with a question: how do I share my knowledge with others in a way that preserves the connections between ideas?\u003C/p>\n\u003Cp>Enter \u003Ca href=\"https://quartz.jzhao.xyz/\">Quartz\u003C/a> - an open-source static site generator designed specifically for transforming Obsidian vaults into interconnected digital gardens. I’ve been using it with Astro to power this very blog, and today I want to show you how you can do the same.\u003C/p>\n\u003Ch2 id=\"what-is-a-digital-garden\">What is a Digital Garden?\u003C/h2>\n\u003Cp>Before we dive into the technical stuff, let’s talk about what a digital garden actually is. Unlike traditional blogs organized chronologically, a digital garden is more like… well, a garden! It’s a collection of interconnected notes that grow over time.\u003C/p>\n\u003Cp>Think of each note as a plant. Some are seedlings (early ideas), some are in full bloom (well-developed thoughts), and others might be somewhere in between. The beauty of a digital garden is that it evolves organically, with connections forming between ideas just as they do in our brains.\u003C/p>\n\u003Ch2 id=\"why-quartz--obsidian--astro\">Why Quartz + Obsidian + Astro?\u003C/h2>\n\u003Cp>I settled on this stack after trying numerous solutions, and here’s why:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Cstrong>Obsidian\u003C/strong>: Provides a fantastic editing experience with bi-directional linking, graph views, and markdown support.\u003C/li>\n\u003Cli>\u003Cstrong>Quartz\u003C/strong>: Transforms Obsidian vaults into interconnected websites with minimal configuration.\u003C/li>\n\u003Cli>\u003Cstrong>Astro\u003C/strong>: Adds flexibility for custom layouts, components, and integrations not available in Quartz alone.\u003C/li>\n\u003C/ul>\n\u003Cp>It’s a match made in heaven - I get the best note-taking experience with Obsidian, the connection-preserving features of Quartz, and the full power of a modern web framework with Astro.\u003C/p>\n\u003Ch2 id=\"setting-up-your-digital-garden\">Setting Up Your Digital Garden\u003C/h2>\n\u003Cp>Let’s walk through how to set this up step by step.\u003C/p>\n\u003Ch3 id=\"step-1-install-obsidian-and-create-a-vault\">Step 1: Install Obsidian and Create a Vault\u003C/h3>\n\u003Cp>If you haven’t already, \u003Ca href=\"https://obsidian.md/\">download Obsidian\u003C/a> and create a new vault for your digital garden content. I recommend having a separate vault for public content to keep it clean.\u003C/p>\n\u003Ch3 id=\"step-2-set-up-quartz\">Step 2: Set Up Quartz\u003C/h3>\n\u003Cp>Quartz is essentially a template for your Obsidian content. Here’s how to get it running:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Clone the Quartz repository\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">git\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> clone\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> https://github.com/jackyzha0/quartz.git\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">cd\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> quartz\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Install dependencies\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">npm\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> install\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Copy your Obsidian vault content to the content folder\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># (or symlink it, which is what I do)\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">ln\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -s\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /path/to/your/obsidian/vault\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> content\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Once installed, you can customize your Quartz configuration in the \u003Ccode>quartz.config.ts\u003C/code> file. Here’s a snippet of mine:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"typescript\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\">// quartz.config.ts\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\">const\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> config\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#8BE9FD;font-style:italic\"> QuartzConfig\u003C/span>\u003Cspan style=\"color:#FF79C6\"> =\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> configuration\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> pageTitle\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">LaForceIT Digital Garden\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> enableSPA\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> true\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> enablePopovers\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> true\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> analytics\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> provider\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">plausible\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> baseUrl\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">blog.laforceit.com\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> ignorePatterns\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">private\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">templates\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">.obsidian\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">],\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> theme\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> typography\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> header\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Space Grotesk\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> body\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Space Grotesk\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> code\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">JetBrains Mono\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> colors\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> lightMode\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> light\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">#fafafa\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> lightgray\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">#e5e5e5\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> gray\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">#b8b8b8\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> darkgray\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">#4e4e4e\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> dark\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">#2b2b2b\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> secondary\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">#284b63\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> tertiary\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">#84a59d\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> highlight\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">rgba(143, 159, 169, 0.15)\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> darkMode\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> light\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">#050a18\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> lightgray\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">#0f172a\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> gray\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">#1e293b\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> darkgray\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">#94a3b8\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> dark\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">#e2e8f0\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> secondary\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">#06b6d4\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> tertiary\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">#3b82f6\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> highlight\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">rgba(6, 182, 212, 0.15)\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> plugins\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> transformers\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> // plugins here\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> ],\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> filters\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> // filters here\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> ],\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> emitters\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> // emitters here\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> ],\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">};\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"step-3-integrating-with-astro\">Step 3: Integrating with Astro\u003C/h3>\n\u003Cp>Now, where Quartz ends and Astro begins is where the magic really happens. Here’s how I integrated them:\u003C/p>\n\u003Col>\n\u003Cli>Create a new Astro project:\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">npm\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> create\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> astro@latest\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> my-digital-garden\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">cd\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> my-digital-garden\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Col start=\"2\">\n\u003Cli>Set up your Astro project structure:\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"plaintext\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan>my-digital-garden/\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>├── public/\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>├── src/\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>│ ├── components/\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>│ ├── layouts/\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>│ ├── pages/\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>│ │ └── index.astro\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>│ └── content/ (this will point to your Quartz content)\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>├── astro.config.mjs\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>└── package.json\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Col start=\"3\">\n\u003Cli>Configure Astro to work with Quartz’s output:\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"typescript\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\">// astro.config.mjs\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\">import\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> { defineConfig } \u003C/span>\u003Cspan style=\"color:#FF79C6\">from\u003C/span>\u003Cspan style=\"color:#E9F284\"> '\u003C/span>\u003Cspan style=\"color:#F1FA8C\">astro/config\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\">export\u003C/span>\u003Cspan style=\"color:#FF79C6\"> default\u003C/span>\u003Cspan style=\"color:#50FA7B\"> defineConfig\u003C/span>\u003Cspan style=\"color:#F8F8F2\">({\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> integrations\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> // Your integrations here\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> ],\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> markdown\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> remarkPlugins\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> // The same remark plugins used in Quartz\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> ],\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> rehypePlugins\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> // The same rehype plugins used in Quartz\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> ]\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">});\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Col start=\"4\">\n\u003Cli>Create a component for the Obsidian graph view (similar to what I use on this blog):\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"astro\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\">---\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\">// Graph.astro\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\">---\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"><\u003C/span>\u003Cspan style=\"color:#FF79C6\">div\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\"> class\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">graph-container\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> <\u003C/span>\u003Cspan style=\"color:#FF79C6\">div\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\"> class\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">graph-visualization\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> <\u003C/span>\u003Cspan style=\"color:#FF79C6\">div\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\"> class\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">graph-overlay\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">></\u003C/span>\u003Cspan style=\"color:#FF79C6\">div\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> <\u003C/span>\u003Cspan style=\"color:#FF79C6\">div\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\"> class\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">graph-nodes\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\"> id\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">obsidian-graph\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">></\u003C/span>\u003Cspan style=\"color:#FF79C6\">div\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> </\u003C/span>\u003Cspan style=\"color:#FF79C6\">div\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> <\u003C/span>\u003Cspan style=\"color:#FF79C6\">div\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\"> class\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">graph-caption\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>Interactive visualization of interconnected notes</\u003C/span>\u003Cspan style=\"color:#FF79C6\">div\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"></\u003C/span>\u003Cspan style=\"color:#FF79C6\">div\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"><\u003C/span>\u003Cspan style=\"color:#FF79C6\">script\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\"> src\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">/blog/scripts/neural-network.js\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\"> defer\u003C/span>\u003Cspan style=\"color:#F8F8F2\">></\u003C/span>\u003Cspan style=\"color:#FF79C6\">script\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"><\u003C/span>\u003Cspan style=\"color:#FF79C6\">style\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B;font-style:italic\"> .graph-container\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> width\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 100\u003C/span>\u003Cspan style=\"color:#FF79C6\">%\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> height\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 400\u003C/span>\u003Cspan style=\"color:#FF79C6\">px\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> position\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> relative\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> border-radius\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 0.75\u003C/span>\u003Cspan style=\"color:#FF79C6\">rem\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> overflow\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> hidden\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> background\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> rgba\u003C/span>\u003Cspan style=\"color:#F8F8F2\">(\u003C/span>\u003Cspan style=\"color:#BD93F9\">15\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#BD93F9\">23\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#BD93F9\">42\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#BD93F9\">0.6\u003C/span>\u003Cspan style=\"color:#F8F8F2\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> border\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 1\u003C/span>\u003Cspan style=\"color:#FF79C6\">px\u003C/span>\u003Cspan style=\"color:#BD93F9\"> solid\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> rgba\u003C/span>\u003Cspan style=\"color:#F8F8F2\">(\u003C/span>\u003Cspan style=\"color:#BD93F9\">56\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#BD93F9\">189\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#BD93F9\">248\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#BD93F9\">0.2\u003C/span>\u003Cspan style=\"color:#F8F8F2\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B;font-style:italic\"> .graph-visualization\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> width\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 100\u003C/span>\u003Cspan style=\"color:#FF79C6\">%\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> height\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 100\u003C/span>\u003Cspan style=\"color:#FF79C6\">%\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> position\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> relative\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B;font-style:italic\"> .graph-overlay\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> position\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> absolute\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> top\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 0\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> left\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 0\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> width\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 100\u003C/span>\u003Cspan style=\"color:#FF79C6\">%\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> height\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 100\u003C/span>\u003Cspan style=\"color:#FF79C6\">%\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> background\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> radial-gradient\u003C/span>\u003Cspan style=\"color:#F8F8F2\">(\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> circle\u003C/span>\u003Cspan style=\"color:#FF79C6\"> at\u003C/span>\u003Cspan style=\"color:#BD93F9\"> center\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> transparent\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 0\u003C/span>\u003Cspan style=\"color:#FF79C6\">%\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> rgba\u003C/span>\u003Cspan style=\"color:#F8F8F2\">(\u003C/span>\u003Cspan style=\"color:#BD93F9\">15\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#BD93F9\">23\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#BD93F9\">42\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#BD93F9\">0.5\u003C/span>\u003Cspan style=\"color:#F8F8F2\">) \u003C/span>\u003Cspan style=\"color:#BD93F9\">100\u003C/span>\u003Cspan style=\"color:#FF79C6\">%\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> );\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> z-index\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 1\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> pointer-events\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> none\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B;font-style:italic\"> .graph-nodes\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> width\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 100\u003C/span>\u003Cspan style=\"color:#FF79C6\">%\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> height\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 100\u003C/span>\u003Cspan style=\"color:#FF79C6\">%\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> position\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> relative\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> z-index\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 2\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B;font-style:italic\"> .graph-caption\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> position\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> absolute\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> bottom\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 0.75\u003C/span>\u003Cspan style=\"color:#FF79C6\">rem\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> left\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 0\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> width\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 100\u003C/span>\u003Cspan style=\"color:#FF79C6\">%\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> text-align\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> center\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> color\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> rgba\u003C/span>\u003Cspan style=\"color:#F8F8F2\">(\u003C/span>\u003Cspan style=\"color:#BD93F9\">148\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#BD93F9\">163\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#BD93F9\">184\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#BD93F9\">0.8\u003C/span>\u003Cspan style=\"color:#F8F8F2\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> font-size\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 0.875\u003C/span>\u003Cspan style=\"color:#FF79C6\">rem\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> z-index\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 3\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"></\u003C/span>\u003Cspan style=\"color:#FF79C6\">style\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"writing-content-for-your-digital-garden\">Writing Content for Your Digital Garden\u003C/h2>\n\u003Cp>Now that you have the technical setup, let’s talk about how to structure your content. Here’s how I approach it:\u003C/p>\n\u003Ch3 id=\"1-use-meaningful-frontmatter\">1. Use Meaningful Frontmatter\u003C/h3>\n\u003Cp>Each note should have frontmatter that helps organize and categorize it:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"markdown\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">---\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">title\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Building a Digital Garden\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">description\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">How to create a connected knowledge base with Obsidian and Quartz\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">pubDate\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#FFB86C\"> 2023-11-05\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">updatedDate\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#FFB86C\"> 2024-02-10\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">category\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Knowledge Management\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">tags\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">digital-garden\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">obsidian\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">quartz\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">notes\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">]\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">---\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"2-create-meaningful-connections\">2. Create Meaningful Connections\u003C/h3>\n\u003Cp>The power of a digital garden comes from connections. Use Obsidian’s \u003Ccode>[[wiki-links]]\u003C/code> liberally to connect related concepts:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"markdown\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">I'm using the [[quartz-digital-garden|Quartz framework]] to power my digital garden. It works well with [[obsidian-setup|my Obsidian workflow]].\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"3-use-consistent-structure-for-your-notes\">3. Use Consistent Structure for Your Notes\u003C/h3>\n\u003Cp>I follow a template for most of my notes to maintain consistency:\u003C/p>\n\u003Cul>\n\u003Cli>Brief introduction/definition\u003C/li>\n\u003Cli>Why it matters\u003C/li>\n\u003Cli>Key concepts\u003C/li>\n\u003Cli>Examples or code snippets\u003C/li>\n\u003Cli>References to related notes\u003C/li>\n\u003Cli>External resources\u003C/li>\n\u003C/ul>\n\u003Ch3 id=\"4-leverage-obsidian-features\">4. Leverage Obsidian Features\u003C/h3>\n\u003Cp>Make use of Obsidian’s unique features that Quartz preserves:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Cstrong>Callouts\u003C/strong> for highlighting important information\u003C/li>\n\u003Cli>\u003Cstrong>Dataview\u003C/strong> for creating dynamic content (if using the Dataview plugin)\u003C/li>\n\u003Cli>\u003Cstrong>Graphs\u003C/strong> to visualize connections\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"deploying-your-digital-garden\">Deploying Your Digital Garden\u003C/h2>\n\u003Cp>Here’s how I deploy my digital garden to Cloudflare Pages:\u003C/p>\n\u003Col>\n\u003Cli>\u003Cstrong>Build Configuration\u003C/strong>:\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"javascript\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\">// Build command\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">astro build\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\">// Output directory\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">dist\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Col start=\"2\">\n\u003Cli>\u003Cstrong>Automated Deployment from Git\u003C/strong>:\u003C/li>\n\u003C/ol>\n\u003Cp>I have a GitHub action that publishes my content whenever I push changes:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Deploy to Cloudflare Pages\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\">on\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> push\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> branches\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003Cspan style=\"color:#F1FA8C\">main\u003C/span>\u003Cspan style=\"color:#F8F8F2\">]\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">jobs\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> deploy\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> runs-on\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ubuntu-latest\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> steps\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> uses\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> actions/checkout@v3\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> with\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> submodules\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> true\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> uses\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> actions/setup-node@v3\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> with\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> node-version\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 18\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Install Dependencies\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> run\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> npm ci\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Build\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> run\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> npm run build\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Deploy to Cloudflare Pages\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> uses\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> cloudflare/pages-action@v1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> with\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> apiToken\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ${{ secrets.CLOUDFLARE_API_TOKEN }}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> accountId\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> projectName\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> digital-garden\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> directory\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> dist\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"my-digital-garden-workflow\">My Digital Garden Workflow\u003C/h2>\n\u003Cp>Here’s my actual workflow for maintaining my digital garden:\u003C/p>\n\u003Col>\n\u003Cli>\u003Cstrong>Daily note-taking\u003C/strong> in Obsidian (private vault)\u003C/li>\n\u003Cli>\u003Cstrong>Weekly review\u003C/strong> where I refine notes and connections\u003C/li>\n\u003Cli>\u003Cstrong>Publishing prep\u003C/strong> where I move polished notes to my public vault\u003C/li>\n\u003Cli>\u003Cstrong>Git commit and push\u003C/strong> which triggers the deployment\u003C/li>\n\u003C/ol>\n\u003Cp>The beauty of this system is that my private thinking and public sharing use the same tools and formats, reducing friction between capturing thoughts and sharing them.\u003C/p>\n\u003Ch2 id=\"adding-interactive-elements\">Adding Interactive Elements\u003C/h2>\n\u003Cp>One of my favorite parts of using Astro with Quartz is that I can add interactive elements to my digital garden. For example, the neural graph visualization you see on this blog:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"javascript\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\">// Simplified version of the neural network graph code\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">document.\u003C/span>\u003Cspan style=\"color:#50FA7B\">addEventListener\u003C/span>\u003Cspan style=\"color:#F8F8F2\">(\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003Cspan style=\"color:#F1FA8C\">DOMContentLoaded\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, () \u003C/span>\u003Cspan style=\"color:#FF79C6\">=>\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> const\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> container \u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> document.\u003C/span>\u003Cspan style=\"color:#50FA7B\">querySelector\u003C/span>\u003Cspan style=\"color:#F8F8F2\">(\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003Cspan style=\"color:#F1FA8C\">.graph-nodes\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003Cspan style=\"color:#F8F8F2\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> if\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> (\u003C/span>\u003Cspan style=\"color:#FF79C6\">!\u003C/span>\u003Cspan style=\"color:#F8F8F2\">container) \u003C/span>\u003Cspan style=\"color:#FF79C6\">return\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> // Configuration\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> const\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> CONNECTION_DISTANCE \u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 30\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> const\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> MIN_NODE_SIZE \u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 4\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> const\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> MAX_NODE_SIZE \u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 12\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> // Fetch blog data from the same origin\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> async\u003C/span>\u003Cspan style=\"color:#FF79C6\"> function\u003C/span>\u003Cspan style=\"color:#50FA7B\"> fetchQuartzData\u003C/span>\u003Cspan style=\"color:#F8F8F2\">() {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> // In production, fetch from your actual API\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> return\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> nodes\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> id\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> '\u003C/span>\u003Cspan style=\"color:#F1FA8C\">digital-garden\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> title\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> '\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Digital Garden\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> tags\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003Cspan style=\"color:#F1FA8C\">knowledge-management\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003Cspan style=\"color:#F1FA8C\">notes\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003Cspan style=\"color:#F8F8F2\">],\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> category\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> '\u003C/span>\u003Cspan style=\"color:#F1FA8C\">concept\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> // More nodes here\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> ],\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> links\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> { source\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> '\u003C/span>\u003Cspan style=\"color:#F1FA8C\">digital-garden\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, target\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> '\u003C/span>\u003Cspan style=\"color:#F1FA8C\">obsidian\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> // More links here\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> ]\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> };\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> // Create the visualization\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\"> fetchQuartzData\u003C/span>\u003Cspan style=\"color:#F8F8F2\">().\u003C/span>\u003Cspan style=\"color:#50FA7B\">then\u003C/span>\u003Cspan style=\"color:#F8F8F2\">(\u003C/span>\u003Cspan style=\"color:#FFB86C;font-style:italic\">graphData\u003C/span>\u003Cspan style=\"color:#FF79C6\"> =>\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> // Create nodes and connections\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> // (implementation details omitted for brevity)\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> });\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">});\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"tips-for-a-successful-digital-garden\">Tips for a Successful Digital Garden\u003C/h2>\n\u003Cp>After maintaining my digital garden for over a year, here are my top tips:\u003C/p>\n\u003Col>\n\u003Cli>\n\u003Cp>\u003Cstrong>Start small\u003C/strong> - Begin with a few well-connected notes rather than trying to publish everything at once.\u003C/p>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>Focus on connections\u003C/strong> - The value is in the links between notes, not just the notes themselves.\u003C/p>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>Embrace imperfection\u003C/strong> - Digital gardens are meant to grow and evolve; they’re never “finished.”\u003C/p>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>Build in public\u003C/strong> - Share your process and learnings as you go.\u003C/p>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>Use consistent formatting\u003C/strong> - Makes it easier for readers to navigate your garden.\u003C/p>\n\u003C/li>\n\u003C/ol>\n\u003Ch2 id=\"the-impact-of-my-digital-garden\">The Impact of My Digital Garden\u003C/h2>\n\u003Cp>Since starting my digital garden, I’ve experienced several unexpected benefits:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Cstrong>Clearer thinking\u003C/strong> - Writing for an audience forces me to clarify my thoughts.\u003C/li>\n\u003Cli>\u003Cstrong>Unexpected connections\u003C/strong> - I’ve discovered relationships between ideas I hadn’t noticed before.\u003C/li>\n\u003Cli>\u003Cstrong>Community building\u003C/strong> - I’ve connected with others interested in the same topics.\u003C/li>\n\u003Cli>\u003Cstrong>Learning accountability\u003C/strong> - Publishing regularly motivates me to keep learning.\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"wrapping-up\">Wrapping Up\u003C/h2>\n\u003Cp>Building a digital garden with Quartz, Obsidian, and Astro has transformed how I learn and share knowledge. It’s become so much more than a blog - it’s a living representation of my thinking that grows more valuable with each connection I make.\u003C/p>\n\u003Cp>If you’re considering starting your own digital garden, I hope this guide gives you a solid foundation. Remember, the best garden is the one you actually tend to, so start simple and let it grow naturally over time.\u003C/p>\n\u003Cp>What about you? Are you maintaining a digital garden or thinking about starting one? I’d love to hear about your experience in the comments!\u003C/p>\n\u003Chr>\n\u003Cp>\u003Cem>This post was last updated on February 10, 2024 with information about the latest Quartz configuration options and integration with Astro.\u003C/em>\u003C/p>",{"headings":835,"localImagePaths":883,"remoteImagePaths":884,"frontmatter":885,"imagePaths":889},[836,837,840,843,846,849,852,855,858,861,864,867,870,873,876,879,882],{"depth":55,"slug":460,"text":461},{"depth":55,"slug":838,"text":839},"why-quartz--obsidian--astro","Why Quartz + Obsidian + Astro?",{"depth":55,"slug":841,"text":842},"setting-up-your-digital-garden","Setting Up Your Digital Garden",{"depth":97,"slug":844,"text":845},"step-1-install-obsidian-and-create-a-vault","Step 1: Install Obsidian and Create a Vault",{"depth":97,"slug":847,"text":848},"step-2-set-up-quartz","Step 2: Set Up Quartz",{"depth":97,"slug":850,"text":851},"step-3-integrating-with-astro","Step 3: Integrating with Astro",{"depth":55,"slug":853,"text":854},"writing-content-for-your-digital-garden","Writing Content for Your Digital Garden",{"depth":97,"slug":856,"text":857},"1-use-meaningful-frontmatter","1. Use Meaningful Frontmatter",{"depth":97,"slug":859,"text":860},"2-create-meaningful-connections","2. Create Meaningful Connections",{"depth":97,"slug":862,"text":863},"3-use-consistent-structure-for-your-notes","3. Use Consistent Structure for Your Notes",{"depth":97,"slug":865,"text":866},"4-leverage-obsidian-features","4. Leverage Obsidian Features",{"depth":55,"slug":868,"text":869},"deploying-your-digital-garden","Deploying Your Digital Garden",{"depth":55,"slug":871,"text":872},"my-digital-garden-workflow","My Digital Garden Workflow",{"depth":55,"slug":874,"text":875},"adding-interactive-elements","Adding Interactive Elements",{"depth":55,"slug":877,"text":878},"tips-for-a-successful-digital-garden","Tips for a Successful Digital Garden",{"depth":55,"slug":880,"text":881},"the-impact-of-my-digital-garden","The Impact of My Digital Garden",{"depth":55,"slug":563,"text":564},[],[],{"title":821,"description":822,"pubDate":886,"updatedDate":887,"category":507,"tags":888,"heroImage":17},["Date","2025-04-18T00:00:00.000Z"],["Date","2025-04-19T00:00:00.000Z"],[826,827,448,449,828],[],"quartz-digital-garden.md","index",{"id":891,"data":893,"body":900,"filePath":901,"digest":902,"rendered":903,"legacyId":918},{"title":894,"description":895,"pubDate":896,"heroImage":445,"category":897,"tags":898},"Welcome to LaForce IT Blog","A collection of articles, guides, and insights on Kubernetes, DevOps, and home lab infrastructure","2023-12-01","General",[9,899],"introduction","# My Public Blog\n\nWelcome to my blog, where I share more polished thoughts and project write-ups.test\n\n## Recent Posts\n- [[Public/Blog/posts/starting-my-digital-garden|Starting My Digital Garden]] - My first post explaining this site\n- [[Public/Blog/posts/starting-my-digital-garden|Starting My Digital Garden]] - My first post explaining this site","src/content/blog/index.md","e2dede170c9b9942",{"html":904,"metadata":905},"\u003Ch1 id=\"my-public-blog\">My Public Blog\u003C/h1>\n\u003Cp>Welcome to my blog, where I share more polished thoughts and project write-ups.test\u003C/p>\n\u003Ch2 id=\"recent-posts\">Recent Posts\u003C/h2>\n\u003Cul>\n\u003Cli>[[Public/Blog/posts/starting-my-digital-garden|Starting My Digital Garden]] - My first post explaining this site\u003C/li>\n\u003Cli>[[Public/Blog/posts/starting-my-digital-garden|Starting My Digital Garden]] - My first post explaining this site\u003C/li>\n\u003C/ul>",{"headings":906,"localImagePaths":913,"remoteImagePaths":914,"frontmatter":915,"imagePaths":917},[907,910],{"depth":52,"slug":908,"text":909},"my-public-blog","My Public Blog",{"depth":55,"slug":911,"text":912},"recent-posts","Recent Posts",[],[],{"title":894,"description":895,"pubDate":896,"heroImage":445,"category":897,"tags":916},[9,899],[],"index.md","external-posts/placeholder",{"id":919,"data":921,"body":928,"filePath":929,"digest":930,"rendered":931,"legacyId":943},{"title":922,"description":923,"pubDate":924,"category":925,"tags":926,"draft":182},"External Posts Collection","A placeholder document for the external-posts collection",["Date","2025-04-18T00:00:00.000Z"],"External",[927],"placeholder","# External Posts Collection\n\nThis is a placeholder file for the external-posts collection.","src/content/blog/external-posts/placeholder.md","042be9b97bac3b27",{"html":932,"metadata":933},"\u003Ch1 id=\"external-posts-collection\">External Posts Collection\u003C/h1>\n\u003Cp>This is a placeholder file for the external-posts collection.\u003C/p>",{"headings":934,"localImagePaths":937,"remoteImagePaths":938,"frontmatter":939,"imagePaths":942},[935],{"depth":52,"slug":936,"text":922},"external-posts-collection",[],[],{"title":922,"description":923,"pubDate":940,"category":925,"tags":941,"draft":182},["Date","2025-04-18T00:00:00.000Z"],[927],[],"external-posts/placeholder.md","guides/container-orchestration",{"id":944,"data":946,"body":954,"filePath":955,"digest":956,"rendered":957,"legacyId":968},{"title":947,"description":948,"pubDate":949,"heroImage":950,"category":951,"tags":952,"draft":43},"Container Orchestration Guide","Master container orchestration with Docker Compose and Kubernetes","2024-03-20","/blog/images/container-orchestration.jpg","Guides",[180,582,636,953],"orchestration","\u003Cdiv class=\"draft-indicator\">\n \u003Cspan class=\"draft-icon\">⚠️\u003C/span>\n \u003Cspan class=\"draft-text\">This article is a draft and needs to be written\u003C/span>\n\u003C/div>\n\n# Container Orchestration Guide\n\nThis guide will walk you through container orchestration strategies and best practices. We'll cover:\n\n- Docker Compose basics\n- Kubernetes fundamentals\n- Service deployment\n- Container networking\n- Resource management\n- Service discovery\n- Load balancing\n- Rolling updates\n- Health monitoring\n- Scaling strategies\n\n[Content coming soon...]\n\n\u003Cstyle>\n.draft-indicator {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n background: rgba(234, 179, 8, 0.1);\n border: 1px solid rgba(234, 179, 8, 0.2);\n padding: 1rem;\n border-radius: 8px;\n margin-bottom: 2rem;\n}\n\n.draft-icon {\n font-size: 1.5rem;\n}\n\n.draft-text {\n color: rgb(234, 179, 8);\n font-weight: 500;\n}\n\u003C/style>","src/content/blog/guides/container-orchestration.md","cc8975cd7544c3ba",{"html":958,"metadata":959},"\u003Cdiv class=\"draft-indicator\">\n \u003Cspan class=\"draft-icon\">⚠️\u003C/span>\n \u003Cspan class=\"draft-text\">This article is a draft and needs to be written\u003C/span>\n\u003C/div>\n\u003Ch1 id=\"container-orchestration-guide\">Container Orchestration Guide\u003C/h1>\n\u003Cp>This guide will walk you through container orchestration strategies and best practices. We’ll cover:\u003C/p>\n\u003Cul>\n\u003Cli>Docker Compose basics\u003C/li>\n\u003Cli>Kubernetes fundamentals\u003C/li>\n\u003Cli>Service deployment\u003C/li>\n\u003Cli>Container networking\u003C/li>\n\u003Cli>Resource management\u003C/li>\n\u003Cli>Service discovery\u003C/li>\n\u003Cli>Load balancing\u003C/li>\n\u003Cli>Rolling updates\u003C/li>\n\u003Cli>Health monitoring\u003C/li>\n\u003Cli>Scaling strategies\u003C/li>\n\u003C/ul>\n\u003Cp>[Content coming soon…]\u003C/p>\n\u003Cstyle>\n.draft-indicator {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n background: rgba(234, 179, 8, 0.1);\n border: 1px solid rgba(234, 179, 8, 0.2);\n padding: 1rem;\n border-radius: 8px;\n margin-bottom: 2rem;\n}\n\n.draft-icon {\n font-size: 1.5rem;\n}\n\n.draft-text {\n color: rgb(234, 179, 8);\n font-weight: 500;\n}\n\u003C/style>",{"headings":960,"localImagePaths":963,"remoteImagePaths":964,"frontmatter":965,"imagePaths":967},[961],{"depth":52,"slug":962,"text":947},"container-orchestration-guide",[],[],{"title":947,"description":948,"pubDate":949,"heroImage":950,"category":951,"tags":966,"draft":43},[180,582,636,953],[],"guides/container-orchestration.md","guides/homelab-backup-strategy",{"id":969,"data":971,"body":978,"filePath":979,"digest":980,"rendered":981,"legacyId":992},{"title":972,"description":973,"pubDate":949,"heroImage":974,"category":951,"tags":975,"draft":43},"Home Lab Backup Strategy Guide","Comprehensive guide to implementing a robust backup strategy for your home lab","/blog/images/backup-strategy.jpg",[976,977,73,22],"backup","disaster-recovery","\u003Cdiv class=\"draft-indicator\">\n \u003Cspan class=\"draft-icon\">⚠️\u003C/span>\n \u003Cspan class=\"draft-text\">This article is a draft and needs to be written\u003C/span>\n\u003C/div>\n\n# Home Lab Backup Strategy Guide\n\nThis guide will walk you through creating a comprehensive backup strategy for your home lab. We'll cover:\n\n- Backup policy design\n- Data classification\n- Backup tools and solutions\n- Automated backup procedures\n- Off-site backup strategies\n- Disaster recovery planning\n- Data retention policies\n- Backup testing and validation\n- Recovery procedures\n- Monitoring and reporting\n\n[Content coming soon...]\n\n\u003Cstyle>\n.draft-indicator {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n background: rgba(234, 179, 8, 0.1);\n border: 1px solid rgba(234, 179, 8, 0.2);\n padding: 1rem;\n border-radius: 8px;\n margin-bottom: 2rem;\n}\n\n.draft-icon {\n font-size: 1.5rem;\n}\n\n.draft-text {\n color: rgb(234, 179, 8);\n font-weight: 500;\n}\n\u003C/style>","src/content/blog/guides/homelab-backup-strategy.md","b3448768c236b384",{"html":982,"metadata":983},"\u003Cdiv class=\"draft-indicator\">\n \u003Cspan class=\"draft-icon\">⚠️\u003C/span>\n \u003Cspan class=\"draft-text\">This article is a draft and needs to be written\u003C/span>\n\u003C/div>\n\u003Ch1 id=\"home-lab-backup-strategy-guide\">Home Lab Backup Strategy Guide\u003C/h1>\n\u003Cp>This guide will walk you through creating a comprehensive backup strategy for your home lab. We’ll cover:\u003C/p>\n\u003Cul>\n\u003Cli>Backup policy design\u003C/li>\n\u003Cli>Data classification\u003C/li>\n\u003Cli>Backup tools and solutions\u003C/li>\n\u003Cli>Automated backup procedures\u003C/li>\n\u003Cli>Off-site backup strategies\u003C/li>\n\u003Cli>Disaster recovery planning\u003C/li>\n\u003Cli>Data retention policies\u003C/li>\n\u003Cli>Backup testing and validation\u003C/li>\n\u003Cli>Recovery procedures\u003C/li>\n\u003Cli>Monitoring and reporting\u003C/li>\n\u003C/ul>\n\u003Cp>[Content coming soon…]\u003C/p>\n\u003Cstyle>\n.draft-indicator {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n background: rgba(234, 179, 8, 0.1);\n border: 1px solid rgba(234, 179, 8, 0.2);\n padding: 1rem;\n border-radius: 8px;\n margin-bottom: 2rem;\n}\n\n.draft-icon {\n font-size: 1.5rem;\n}\n\n.draft-text {\n color: rgb(234, 179, 8);\n font-weight: 500;\n}\n\u003C/style>",{"headings":984,"localImagePaths":987,"remoteImagePaths":988,"frontmatter":989,"imagePaths":991},[985],{"depth":52,"slug":986,"text":972},"home-lab-backup-strategy-guide",[],[],{"title":972,"description":973,"pubDate":949,"heroImage":974,"category":951,"tags":990,"draft":43},[976,977,73,22],[],"guides/homelab-backup-strategy.md","guides/proxmox-setup",{"id":993,"data":995,"body":1000,"filePath":1001,"digest":1002,"rendered":1003,"legacyId":1014},{"title":996,"description":997,"pubDate":949,"heroImage":998,"category":951,"tags":999,"draft":43},"Proxmox VE Setup Guide","Complete guide to setting up and configuring Proxmox Virtual Environment for your home lab","/blog/images/proxmox-setup.jpg",[75,76,73,22],"\u003Cdiv class=\"draft-indicator\">\n \u003Cspan class=\"draft-icon\">⚠️\u003C/span>\n \u003Cspan class=\"draft-text\">This article is a draft and needs to be written\u003C/span>\n\u003C/div>\n\n# Proxmox VE Setup Guide\n\nThis guide will walk you through setting up Proxmox Virtual Environment for your home lab. We'll cover:\n\n- Installation and initial setup\n- Network configuration\n- Storage management\n- Cluster configuration\n- VM and container management\n- Backup strategies\n- Performance optimization\n- Security hardening\n- High availability setup\n\n[Content coming soon...]\n\n\u003Cstyle>\n.draft-indicator {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n background: rgba(234, 179, 8, 0.1);\n border: 1px solid rgba(234, 179, 8, 0.2);\n padding: 1rem;\n border-radius: 8px;\n margin-bottom: 2rem;\n}\n\n.draft-icon {\n font-size: 1.5rem;\n}\n\n.draft-text {\n color: rgb(234, 179, 8);\n font-weight: 500;\n}\n\u003C/style>","src/content/blog/guides/proxmox-setup.md","66928fba894fca1e",{"html":1004,"metadata":1005},"\u003Cdiv class=\"draft-indicator\">\n \u003Cspan class=\"draft-icon\">⚠️\u003C/span>\n \u003Cspan class=\"draft-text\">This article is a draft and needs to be written\u003C/span>\n\u003C/div>\n\u003Ch1 id=\"proxmox-ve-setup-guide\">Proxmox VE Setup Guide\u003C/h1>\n\u003Cp>This guide will walk you through setting up Proxmox Virtual Environment for your home lab. We’ll cover:\u003C/p>\n\u003Cul>\n\u003Cli>Installation and initial setup\u003C/li>\n\u003Cli>Network configuration\u003C/li>\n\u003Cli>Storage management\u003C/li>\n\u003Cli>Cluster configuration\u003C/li>\n\u003Cli>VM and container management\u003C/li>\n\u003Cli>Backup strategies\u003C/li>\n\u003Cli>Performance optimization\u003C/li>\n\u003Cli>Security hardening\u003C/li>\n\u003Cli>High availability setup\u003C/li>\n\u003C/ul>\n\u003Cp>[Content coming soon…]\u003C/p>\n\u003Cstyle>\n.draft-indicator {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n background: rgba(234, 179, 8, 0.1);\n border: 1px solid rgba(234, 179, 8, 0.2);\n padding: 1rem;\n border-radius: 8px;\n margin-bottom: 2rem;\n}\n\n.draft-icon {\n font-size: 1.5rem;\n}\n\n.draft-text {\n color: rgb(234, 179, 8);\n font-weight: 500;\n}\n\u003C/style>",{"headings":1006,"localImagePaths":1009,"remoteImagePaths":1010,"frontmatter":1011,"imagePaths":1013},[1007],{"depth":52,"slug":1008,"text":996},"proxmox-ve-setup-guide",[],[],{"title":996,"description":997,"pubDate":949,"heroImage":998,"category":951,"tags":1012,"draft":43},[75,76,73,22],[],"guides/proxmox-setup.md","guides/vscode-server-setup",{"id":1015,"data":1017,"body":1025,"filePath":1026,"digest":1027,"rendered":1028,"legacyId":1039},{"title":1018,"description":1019,"pubDate":949,"heroImage":1020,"category":951,"tags":1021,"draft":43},"VS Code Server Remote Development Guide","Set up VS Code Server for remote development in your home lab","/blog/images/vscode-server.jpg",[1022,709,1023,1024],"development","remote","tools","\u003Cdiv class=\"draft-indicator\">\n \u003Cspan class=\"draft-icon\">⚠️\u003C/span>\n \u003Cspan class=\"draft-text\">This article is a draft and needs to be written\u003C/span>\n\u003C/div>\n\n# VS Code Server Remote Development Guide\n\nThis guide will walk you through setting up VS Code Server for remote development. We'll cover:\n\n- Installation and configuration\n- Authentication setup\n- Extension management\n- Git integration\n- Docker development\n- Kubernetes development\n- Remote debugging\n- Performance optimization\n- Security considerations\n- Backup and sync strategies\n\n[Content coming soon...]\n\n\u003Cstyle>\n.draft-indicator {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n background: rgba(234, 179, 8, 0.1);\n border: 1px solid rgba(234, 179, 8, 0.2);\n padding: 1rem;\n border-radius: 8px;\n margin-bottom: 2rem;\n}\n\n.draft-icon {\n font-size: 1.5rem;\n}\n\n.draft-text {\n color: rgb(234, 179, 8);\n font-weight: 500;\n}\n\u003C/style>","src/content/blog/guides/vscode-server-setup.md","f6a617216054f7d2",{"html":1029,"metadata":1030},"\u003Cdiv class=\"draft-indicator\">\n \u003Cspan class=\"draft-icon\">⚠️\u003C/span>\n \u003Cspan class=\"draft-text\">This article is a draft and needs to be written\u003C/span>\n\u003C/div>\n\u003Ch1 id=\"vs-code-server-remote-development-guide\">VS Code Server Remote Development Guide\u003C/h1>\n\u003Cp>This guide will walk you through setting up VS Code Server for remote development. We’ll cover:\u003C/p>\n\u003Cul>\n\u003Cli>Installation and configuration\u003C/li>\n\u003Cli>Authentication setup\u003C/li>\n\u003Cli>Extension management\u003C/li>\n\u003Cli>Git integration\u003C/li>\n\u003Cli>Docker development\u003C/li>\n\u003Cli>Kubernetes development\u003C/li>\n\u003Cli>Remote debugging\u003C/li>\n\u003Cli>Performance optimization\u003C/li>\n\u003Cli>Security considerations\u003C/li>\n\u003Cli>Backup and sync strategies\u003C/li>\n\u003C/ul>\n\u003Cp>[Content coming soon…]\u003C/p>\n\u003Cstyle>\n.draft-indicator {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n background: rgba(234, 179, 8, 0.1);\n border: 1px solid rgba(234, 179, 8, 0.2);\n padding: 1rem;\n border-radius: 8px;\n margin-bottom: 2rem;\n}\n\n.draft-icon {\n font-size: 1.5rem;\n}\n\n.draft-text {\n color: rgb(234, 179, 8);\n font-weight: 500;\n}\n\u003C/style>",{"headings":1031,"localImagePaths":1034,"remoteImagePaths":1035,"frontmatter":1036,"imagePaths":1038},[1032],{"depth":52,"slug":1033,"text":1018},"vs-code-server-remote-development-guide",[],[],{"title":1018,"description":1019,"pubDate":949,"heroImage":1020,"category":951,"tags":1037,"draft":43},[1022,709,1023,1024],[],"guides/vscode-server-setup.md","infrastructure/ha-kubernetes-setup",{"id":1040,"data":1042,"body":1050,"filePath":1051,"digest":1052,"rendered":1053,"legacyId":1064},{"title":1043,"description":1044,"pubDate":949,"heroImage":1045,"category":1046,"tags":1047,"draft":43},"High-Availability Kubernetes Setup Guide","Build a resilient multi-node Kubernetes cluster for production workloads","/blog/images/ha-kubernetes.jpg","Infrastructure",[180,1048,73,1049],"high-availability","clustering","\u003Cdiv class=\"draft-indicator\">\n \u003Cspan class=\"draft-icon\">⚠️\u003C/span>\n \u003Cspan class=\"draft-text\">This article is a draft and needs to be written\u003C/span>\n\u003C/div>\n\n# High-Availability Kubernetes Setup Guide\n\nThis guide will walk you through setting up a highly available Kubernetes cluster. We'll cover:\n\n- Architecture planning\n- Control plane redundancy\n- etcd cluster setup\n- Load balancer configuration\n- Node management\n- Network configuration\n- Storage considerations\n- Backup and disaster recovery\n- Monitoring and alerting\n\n[Content coming soon...]\n\n\u003Cstyle>\n.draft-indicator {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n background: rgba(234, 179, 8, 0.1);\n border: 1px solid rgba(234, 179, 8, 0.2);\n padding: 1rem;\n border-radius: 8px;\n margin-bottom: 2rem;\n}\n\n.draft-icon {\n font-size: 1.5rem;\n}\n\n.draft-text {\n color: rgb(234, 179, 8);\n font-weight: 500;\n}\n\u003C/style>","src/content/blog/infrastructure/ha-kubernetes-setup.md","13bd8c9490d739d5",{"html":1054,"metadata":1055},"\u003Cdiv class=\"draft-indicator\">\n \u003Cspan class=\"draft-icon\">⚠️\u003C/span>\n \u003Cspan class=\"draft-text\">This article is a draft and needs to be written\u003C/span>\n\u003C/div>\n\u003Ch1 id=\"high-availability-kubernetes-setup-guide\">High-Availability Kubernetes Setup Guide\u003C/h1>\n\u003Cp>This guide will walk you through setting up a highly available Kubernetes cluster. We’ll cover:\u003C/p>\n\u003Cul>\n\u003Cli>Architecture planning\u003C/li>\n\u003Cli>Control plane redundancy\u003C/li>\n\u003Cli>etcd cluster setup\u003C/li>\n\u003Cli>Load balancer configuration\u003C/li>\n\u003Cli>Node management\u003C/li>\n\u003Cli>Network configuration\u003C/li>\n\u003Cli>Storage considerations\u003C/li>\n\u003Cli>Backup and disaster recovery\u003C/li>\n\u003Cli>Monitoring and alerting\u003C/li>\n\u003C/ul>\n\u003Cp>[Content coming soon…]\u003C/p>\n\u003Cstyle>\n.draft-indicator {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n background: rgba(234, 179, 8, 0.1);\n border: 1px solid rgba(234, 179, 8, 0.2);\n padding: 1rem;\n border-radius: 8px;\n margin-bottom: 2rem;\n}\n\n.draft-icon {\n font-size: 1.5rem;\n}\n\n.draft-text {\n color: rgb(234, 179, 8);\n font-weight: 500;\n}\n\u003C/style>",{"headings":1056,"localImagePaths":1059,"remoteImagePaths":1060,"frontmatter":1061,"imagePaths":1063},[1057],{"depth":52,"slug":1058,"text":1043},"high-availability-kubernetes-setup-guide",[],[],{"title":1043,"description":1044,"pubDate":949,"heroImage":1045,"category":1046,"tags":1062,"draft":43},[180,1048,73,1049],[],"infrastructure/ha-kubernetes-setup.md","infrastructure/nas-k8s-integration",{"id":1065,"data":1067,"body":1073,"filePath":1074,"digest":1075,"rendered":1076,"legacyId":1087},{"title":1068,"description":1069,"pubDate":949,"heroImage":1070,"category":1046,"tags":1071,"draft":43},"NAS Integration with Kubernetes Guide","Learn how to integrate your NAS storage with Kubernetes for persistent data","/blog/images/nas-integration.jpg",[180,159,1072,73],"nas","\u003Cdiv class=\"draft-indicator\">\n \u003Cspan class=\"draft-icon\">⚠️\u003C/span>\n \u003Cspan class=\"draft-text\">This article is a draft and needs to be written\u003C/span>\n\u003C/div>\n\n# NAS Integration with Kubernetes Guide\n\nThis guide will walk you through integrating your NAS storage with Kubernetes. We'll cover:\n\n- NFS server setup\n- Storage class configuration\n- Persistent volume claims\n- Dynamic provisioning\n- Backup strategies\n- Performance optimization\n- Security considerations\n- Monitoring and maintenance\n- Common troubleshooting\n\n[Content coming soon...]\n\n\u003Cstyle>\n.draft-indicator {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n background: rgba(234, 179, 8, 0.1);\n border: 1px solid rgba(234, 179, 8, 0.2);\n padding: 1rem;\n border-radius: 8px;\n margin-bottom: 2rem;\n}\n\n.draft-icon {\n font-size: 1.5rem;\n}\n\n.draft-text {\n color: rgb(234, 179, 8);\n font-weight: 500;\n}\n\u003C/style>","src/content/blog/infrastructure/nas-k8s-integration.md","d79af380853993ab",{"html":1077,"metadata":1078},"\u003Cdiv class=\"draft-indicator\">\n \u003Cspan class=\"draft-icon\">⚠️\u003C/span>\n \u003Cspan class=\"draft-text\">This article is a draft and needs to be written\u003C/span>\n\u003C/div>\n\u003Ch1 id=\"nas-integration-with-kubernetes-guide\">NAS Integration with Kubernetes Guide\u003C/h1>\n\u003Cp>This guide will walk you through integrating your NAS storage with Kubernetes. We’ll cover:\u003C/p>\n\u003Cul>\n\u003Cli>NFS server setup\u003C/li>\n\u003Cli>Storage class configuration\u003C/li>\n\u003Cli>Persistent volume claims\u003C/li>\n\u003Cli>Dynamic provisioning\u003C/li>\n\u003Cli>Backup strategies\u003C/li>\n\u003Cli>Performance optimization\u003C/li>\n\u003Cli>Security considerations\u003C/li>\n\u003Cli>Monitoring and maintenance\u003C/li>\n\u003Cli>Common troubleshooting\u003C/li>\n\u003C/ul>\n\u003Cp>[Content coming soon…]\u003C/p>\n\u003Cstyle>\n.draft-indicator {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n background: rgba(234, 179, 8, 0.1);\n border: 1px solid rgba(234, 179, 8, 0.2);\n padding: 1rem;\n border-radius: 8px;\n margin-bottom: 2rem;\n}\n\n.draft-icon {\n font-size: 1.5rem;\n}\n\n.draft-text {\n color: rgb(234, 179, 8);\n font-weight: 500;\n}\n\u003C/style>",{"headings":1079,"localImagePaths":1082,"remoteImagePaths":1083,"frontmatter":1084,"imagePaths":1086},[1080],{"depth":52,"slug":1081,"text":1068},"nas-integration-with-kubernetes-guide",[],[],{"title":1068,"description":1069,"pubDate":949,"heroImage":1070,"category":1046,"tags":1085,"draft":43},[180,159,1072,73],[],"infrastructure/nas-k8s-integration.md","infrastructure/network-security",{"id":1088,"data":1090,"body":1096,"filePath":1097,"digest":1098,"rendered":1099,"legacyId":1110},{"title":1091,"description":1092,"pubDate":949,"heroImage":1093,"category":1046,"tags":1094,"draft":43},"Home Lab Network Security Guide","Implement comprehensive network security measures for your home lab","/blog/images/network-security.jpg",[21,18,73,1095],"firewall","\u003Cdiv class=\"draft-indicator\">\n \u003Cspan class=\"draft-icon\">⚠️\u003C/span>\n \u003Cspan class=\"draft-text\">This article is a draft and needs to be written\u003C/span>\n\u003C/div>\n\n# Home Lab Network Security Guide\n\nThis guide will walk you through implementing robust network security for your home lab. We'll cover:\n\n- Network segmentation with VLANs\n- Firewall configuration\n- Intrusion Detection/Prevention\n- Network monitoring\n- Access control policies\n- SSL/TLS implementation\n- Security logging\n- Vulnerability scanning\n- Incident response\n- Security best practices\n\n[Content coming soon...]\n\n\u003Cstyle>\n.draft-indicator {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n background: rgba(234, 179, 8, 0.1);\n border: 1px solid rgba(234, 179, 8, 0.2);\n padding: 1rem;\n border-radius: 8px;\n margin-bottom: 2rem;\n}\n\n.draft-icon {\n font-size: 1.5rem;\n}\n\n.draft-text {\n color: rgb(234, 179, 8);\n font-weight: 500;\n}\n\u003C/style>","src/content/blog/infrastructure/network-security.md","77dca08c9e5440e5",{"html":1100,"metadata":1101},"\u003Cdiv class=\"draft-indicator\">\n \u003Cspan class=\"draft-icon\">⚠️\u003C/span>\n \u003Cspan class=\"draft-text\">This article is a draft and needs to be written\u003C/span>\n\u003C/div>\n\u003Ch1 id=\"home-lab-network-security-guide\">Home Lab Network Security Guide\u003C/h1>\n\u003Cp>This guide will walk you through implementing robust network security for your home lab. We’ll cover:\u003C/p>\n\u003Cul>\n\u003Cli>Network segmentation with VLANs\u003C/li>\n\u003Cli>Firewall configuration\u003C/li>\n\u003Cli>Intrusion Detection/Prevention\u003C/li>\n\u003Cli>Network monitoring\u003C/li>\n\u003Cli>Access control policies\u003C/li>\n\u003Cli>SSL/TLS implementation\u003C/li>\n\u003Cli>Security logging\u003C/li>\n\u003Cli>Vulnerability scanning\u003C/li>\n\u003Cli>Incident response\u003C/li>\n\u003Cli>Security best practices\u003C/li>\n\u003C/ul>\n\u003Cp>[Content coming soon…]\u003C/p>\n\u003Cstyle>\n.draft-indicator {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n background: rgba(234, 179, 8, 0.1);\n border: 1px solid rgba(234, 179, 8, 0.2);\n padding: 1rem;\n border-radius: 8px;\n margin-bottom: 2rem;\n}\n\n.draft-icon {\n font-size: 1.5rem;\n}\n\n.draft-text {\n color: rgb(234, 179, 8);\n font-weight: 500;\n}\n\u003C/style>",{"headings":1102,"localImagePaths":1105,"remoteImagePaths":1106,"frontmatter":1107,"imagePaths":1109},[1103],{"depth":52,"slug":1104,"text":1091},"home-lab-network-security-guide",[],[],{"title":1091,"description":1092,"pubDate":949,"heroImage":1093,"category":1046,"tags":1108,"draft":43},[21,18,73,1095],[],"infrastructure/network-security.md","infrastructure/secure-vpn",{"id":1111,"data":1113,"body":1119,"filePath":1120,"digest":1121,"rendered":1122,"legacyId":1133},{"title":1114,"description":1115,"pubDate":949,"heroImage":1116,"category":1046,"tags":1117,"draft":43},"Secure VPN Access Setup Guide","Set up a secure VPN solution for remote access to your home lab","/blog/images/secure-vpn.jpg",[21,1118,18,73],"vpn","\u003Cdiv class=\"draft-indicator\">\n \u003Cspan class=\"draft-icon\">⚠️\u003C/span>\n \u003Cspan class=\"draft-text\">This article is a draft and needs to be written\u003C/span>\n\u003C/div>\n\n# Secure VPN Access Setup Guide\n\nThis guide will walk you through setting up secure VPN access to your home lab. We'll cover:\n\n- VPN server selection and setup\n- Certificate management\n- Network configuration\n- Client setup\n- Split tunneling\n- Access control\n- Monitoring and logging\n- Security best practices\n- Troubleshooting common issues\n\n[Content coming soon...]\n\n\u003Cstyle>\n.draft-indicator {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n background: rgba(234, 179, 8, 0.1);\n border: 1px solid rgba(234, 179, 8, 0.2);\n padding: 1rem;\n border-radius: 8px;\n margin-bottom: 2rem;\n}\n\n.draft-icon {\n font-size: 1.5rem;\n}\n\n.draft-text {\n color: rgb(234, 179, 8);\n font-weight: 500;\n}\n\u003C/style>","src/content/blog/infrastructure/secure-vpn.md","074d965970ccb0b3",{"html":1123,"metadata":1124},"\u003Cdiv class=\"draft-indicator\">\n \u003Cspan class=\"draft-icon\">⚠️\u003C/span>\n \u003Cspan class=\"draft-text\">This article is a draft and needs to be written\u003C/span>\n\u003C/div>\n\u003Ch1 id=\"secure-vpn-access-setup-guide\">Secure VPN Access Setup Guide\u003C/h1>\n\u003Cp>This guide will walk you through setting up secure VPN access to your home lab. We’ll cover:\u003C/p>\n\u003Cul>\n\u003Cli>VPN server selection and setup\u003C/li>\n\u003Cli>Certificate management\u003C/li>\n\u003Cli>Network configuration\u003C/li>\n\u003Cli>Client setup\u003C/li>\n\u003Cli>Split tunneling\u003C/li>\n\u003Cli>Access control\u003C/li>\n\u003Cli>Monitoring and logging\u003C/li>\n\u003Cli>Security best practices\u003C/li>\n\u003Cli>Troubleshooting common issues\u003C/li>\n\u003C/ul>\n\u003Cp>[Content coming soon…]\u003C/p>\n\u003Cstyle>\n.draft-indicator {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n background: rgba(234, 179, 8, 0.1);\n border: 1px solid rgba(234, 179, 8, 0.2);\n padding: 1rem;\n border-radius: 8px;\n margin-bottom: 2rem;\n}\n\n.draft-icon {\n font-size: 1.5rem;\n}\n\n.draft-text {\n color: rgb(234, 179, 8);\n font-weight: 500;\n}\n\u003C/style>",{"headings":1125,"localImagePaths":1128,"remoteImagePaths":1129,"frontmatter":1130,"imagePaths":1132},[1126],{"depth":52,"slug":1127,"text":1114},"secure-vpn-access-setup-guide",[],[],{"title":1114,"description":1115,"pubDate":949,"heroImage":1116,"category":1046,"tags":1131,"draft":43},[21,1118,18,73],[],"infrastructure/secure-vpn.md","posts/readme",{"id":1134,"data":1136,"body":44,"filePath":1138,"digest":46,"rendered":1139,"legacyId":1150},{"title":40,"description":41,"pubDate":1137,"draft":43},["Date","2025-04-18T00:00:00.000Z"],"src/content/blog/posts/README.md",{"html":48,"metadata":1140},{"headings":1141,"localImagePaths":1145,"remoteImagePaths":1146,"frontmatter":1147,"imagePaths":1149},[1142,1143,1144],{"depth":52,"slug":53,"text":40},{"depth":55,"slug":56,"text":57},{"depth":55,"slug":59,"text":60},[],[],{"title":40,"description":41,"pubDate":1148,"draft":43},["Date","2025-04-18T00:00:00.000Z"],[],"posts/README.md","posts/test",{"id":1151,"data":1153,"filePath":1155,"digest":26,"rendered":1156,"legacyId":1164},{"title":14,"description":15,"pubDate":16,"heroImage":17,"category":18,"tags":1154,"readTime":24},[20,18,21,22,23],"src/content/blog/posts/Test.md",{"html":28,"metadata":1157},{"headings":1158,"localImagePaths":1159,"remoteImagePaths":1160,"frontmatter":1161,"imagePaths":1163},[],[],[],{"title":14,"description":15,"pubDate":16,"heroImage":17,"category":18,"tags":1162,"readTime":24},[20,18,21,22,23],[],"posts/Test.md","posts/k3s-cluster",{"id":1165,"data":1167,"body":1172,"filePath":1173,"digest":1174,"rendered":1175,"legacyId":1186},{"title":174,"description":1168,"pubDate":1169,"heroImage":1170,"category":1046,"tags":1171,"draft":182},"A comprehensive guide to setting up and configuring a lightweight K3s Kubernetes cluster for your home lab",["Date","2025-04-19T00:00:00.000Z"],null,[180,181,73,22,636],"# Setting Up a K3s Kubernetes Cluster\n\nComing soon...","src/content/blog/posts/k3s-cluster.md","531e563f9b52c51d",{"html":1176,"metadata":1177},"\u003Ch1 id=\"setting-up-a-k3s-kubernetes-cluster\">Setting Up a K3s Kubernetes Cluster\u003C/h1>\n\u003Cp>Coming soon…\u003C/p>",{"headings":1178,"localImagePaths":1180,"remoteImagePaths":1181,"frontmatter":1182,"imagePaths":1185},[1179],{"depth":52,"slug":191,"text":174},[],[],{"title":174,"pubDate":1183,"description":1168,"category":1046,"tags":1184,"draft":182,"heroImage":1170},["Date","2025-04-19T00:00:00.000Z"],[180,181,73,22,636],[],"posts/k3s-cluster.md","posts/example",{"id":1187,"data":1189,"body":1199,"filePath":1200,"digest":1201,"rendered":1202,"legacyId":1229},{"title":1190,"description":1191,"pubDate":1192,"heroImage":1193,"category":1194,"tags":1195,"draft":43,"author":1198},"Example Post","This is an example post to demonstrate the blog's functionality",["Date","2023-11-20T00:00:00.000Z"],"/images/example-post.jpg","Demo",[1196,1197,223],"example","demo","LaForce IT","# Example Post\n\nThis is an example post that demonstrates the structure and formatting of a blog post on the LaForce IT blog.\n\n## Introduction\n\nWhen writing blog posts, it's important to have a clear structure that guides the reader through your content. This example post shows how to organize your content effectively.\n\n## Main Content\n\n### Code Blocks\n\nYou can include code snippets like this:\n\n```bash\n# Install dependencies\nnpm install\n\n# Start the development server\nnpm run dev\n```\n\n### Lists\n\nBullet points are great for summarizing information:\n\n- Point one about the topic\n- Point two with more details\n- Point three with a conclusion\n\nNumbered lists work well for step-by-step instructions:\n\n1. First, do this important step\n2. Then, proceed to the next action\n3. Finally, complete the process\n\n### Images\n\nYou can include images with Markdown syntax:\n\n![Alt text for the image](/blog/images/posts//images/example-image.jpg)\n\n## Conclusion\n\nThis example post demonstrates the basic elements you might include in a blog post. Feel free to use this as a template for your own posts.\n\nRemember to:\n- Use clear headings and subheadings\n- Include relevant code examples\n- Add images where helpful\n- Organize content logically","src/content/blog/posts/example.md","b3a8cece32781444",{"html":1203,"metadata":1204},"\u003Ch1 id=\"example-post\">Example Post\u003C/h1>\n\u003Cp>This is an example post that demonstrates the structure and formatting of a blog post on the LaForce IT blog.\u003C/p>\n\u003Ch2 id=\"introduction\">Introduction\u003C/h2>\n\u003Cp>When writing blog posts, it’s important to have a clear structure that guides the reader through your content. This example post shows how to organize your content effectively.\u003C/p>\n\u003Ch2 id=\"main-content\">Main Content\u003C/h2>\n\u003Ch3 id=\"code-blocks\">Code Blocks\u003C/h3>\n\u003Cp>You can include code snippets like this:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Install dependencies\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">npm\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> install\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Start the development server\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">npm\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> run\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> dev\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"lists\">Lists\u003C/h3>\n\u003Cp>Bullet points are great for summarizing information:\u003C/p>\n\u003Cul>\n\u003Cli>Point one about the topic\u003C/li>\n\u003Cli>Point two with more details\u003C/li>\n\u003Cli>Point three with a conclusion\u003C/li>\n\u003C/ul>\n\u003Cp>Numbered lists work well for step-by-step instructions:\u003C/p>\n\u003Col>\n\u003Cli>First, do this important step\u003C/li>\n\u003Cli>Then, proceed to the next action\u003C/li>\n\u003Cli>Finally, complete the process\u003C/li>\n\u003C/ol>\n\u003Ch3 id=\"images\">Images\u003C/h3>\n\u003Cp>You can include images with Markdown syntax:\u003C/p>\n\u003Cp>\u003Cimg src=\"/blog/images/posts//images/example-image.jpg\" alt=\"Alt text for the image\">\u003C/p>\n\u003Ch2 id=\"conclusion\">Conclusion\u003C/h2>\n\u003Cp>This example post demonstrates the basic elements you might include in a blog post. Feel free to use this as a template for your own posts.\u003C/p>\n\u003Cp>Remember to:\u003C/p>\n\u003Cul>\n\u003Cli>Use clear headings and subheadings\u003C/li>\n\u003Cli>Include relevant code examples\u003C/li>\n\u003Cli>Add images where helpful\u003C/li>\n\u003Cli>Organize content logically\u003C/li>\n\u003C/ul>",{"headings":1205,"localImagePaths":1223,"remoteImagePaths":1224,"frontmatter":1225,"imagePaths":1228},[1206,1208,1210,1213,1216,1219,1222],{"depth":52,"slug":1207,"text":1190},"example-post",{"depth":55,"slug":899,"text":1209},"Introduction",{"depth":55,"slug":1211,"text":1212},"main-content","Main Content",{"depth":97,"slug":1214,"text":1215},"code-blocks","Code Blocks",{"depth":97,"slug":1217,"text":1218},"lists","Lists",{"depth":97,"slug":1220,"text":1221},"images","Images",{"depth":55,"slug":162,"text":163},[],[],{"title":1190,"pubDate":1226,"description":1191,"author":1198,"heroImage":1193,"category":1194,"tags":1227,"draft":43},["Date","2023-11-20T00:00:00.000Z"],[1196,1197,223],[],"posts/example.md","posts/proxmox-setup-guide",{"id":1230,"data":1232,"body":78,"filePath":1235,"digest":80,"rendered":1236,"legacyId":1271},{"title":70,"description":71,"pubDate":1233,"heroImage":17,"category":73,"tags":1234,"readTime":77},["Date","2025-04-19T00:00:00.000Z"],[75,76,22,73],"src/content/blog/posts/proxmox-setup-guide.md",{"html":82,"metadata":1237},{"headings":1238,"localImagePaths":1265,"remoteImagePaths":1266,"frontmatter":1267,"imagePaths":1270},[1239,1240,1241,1242,1243,1244,1245,1246,1247,1248,1249,1250,1251,1252,1253,1254,1255,1256,1257,1258,1259,1260,1261,1262,1263,1264],{"depth":52,"slug":86,"text":70},{"depth":55,"slug":88,"text":89},{"depth":55,"slug":91,"text":92},{"depth":55,"slug":94,"text":95},{"depth":97,"slug":98,"text":99},{"depth":97,"slug":101,"text":102},{"depth":97,"slug":104,"text":105},{"depth":55,"slug":107,"text":108},{"depth":97,"slug":110,"text":111},{"depth":97,"slug":113,"text":114},{"depth":97,"slug":116,"text":117},{"depth":119,"slug":120,"text":121},{"depth":119,"slug":123,"text":124},{"depth":97,"slug":126,"text":127},{"depth":119,"slug":129,"text":130},{"depth":119,"slug":132,"text":133},{"depth":55,"slug":135,"text":136},{"depth":97,"slug":138,"text":139},{"depth":97,"slug":141,"text":142},{"depth":55,"slug":144,"text":145},{"depth":97,"slug":147,"text":148},{"depth":55,"slug":150,"text":151},{"depth":97,"slug":153,"text":154},{"depth":97,"slug":156,"text":157},{"depth":97,"slug":159,"text":160},{"depth":55,"slug":162,"text":163},[],[],{"title":70,"description":71,"pubDate":1268,"heroImage":17,"category":73,"tags":1269,"readTime":77},["Date","2025-04-19T00:00:00.000Z"],[75,76,22,73],[],"posts/proxmox-setup-guide.md","posts/k3s-installation-guide",{"id":1272,"data":1274,"body":225,"filePath":1277,"digest":227,"rendered":1278,"legacyId":1296},{"title":219,"description":220,"pubDate":1275,"heroImage":177,"category":180,"tags":1276,"readTime":224},["Date","2025-04-19T00:00:00.000Z"],[180,181,22,223],"src/content/blog/posts/k3s-installation-guide.md",{"html":229,"metadata":1279},{"headings":1280,"localImagePaths":1290,"remoteImagePaths":1291,"frontmatter":1292,"imagePaths":1295},[1281,1282,1283,1284,1285,1286,1287,1288,1289],{"depth":52,"slug":216,"text":219},{"depth":55,"slug":193,"text":194},{"depth":55,"slug":235,"text":236},{"depth":55,"slug":238,"text":239},{"depth":97,"slug":241,"text":242},{"depth":97,"slug":244,"text":245},{"depth":55,"slug":247,"text":248},{"depth":55,"slug":250,"text":251},{"depth":55,"slug":208,"text":209},[],[],{"title":219,"description":220,"pubDate":1293,"heroImage":177,"category":180,"tags":1294,"readTime":224},["Date","2025-04-19T00:00:00.000Z"],[180,181,22,223],[],"posts/k3s-installation-guide.md","posts/gitops-with-flux-cd",{"id":1297,"data":1299,"body":273,"filePath":1302,"digest":275,"rendered":1303,"legacyId":1323},{"title":263,"description":264,"pubDate":1300,"heroImage":17,"category":266,"tags":1301,"readTime":272},["Date","2025-04-19T00:00:00.000Z"],[180,268,269,270,271],"src/content/blog/posts/gitops-with-flux-cd.md",{"html":277,"metadata":1304},{"headings":1305,"localImagePaths":1317,"remoteImagePaths":1318,"frontmatter":1319,"imagePaths":1322},[1306,1307,1308,1309,1310,1311,1312,1313,1314,1315,1316],{"depth":52,"slug":260,"text":263},{"depth":55,"slug":282,"text":283},{"depth":55,"slug":285,"text":286},{"depth":55,"slug":94,"text":95},{"depth":97,"slug":193,"text":194},{"depth":97,"slug":290,"text":291},{"depth":55,"slug":293,"text":294},{"depth":55,"slug":296,"text":297},{"depth":97,"slug":299,"text":300},{"depth":97,"slug":302,"text":303},{"depth":55,"slug":162,"text":163},[],[],{"title":263,"description":264,"pubDate":1320,"heroImage":17,"category":266,"tags":1321,"readTime":272},["Date","2025-04-19T00:00:00.000Z"],[180,268,269,270,271],[],"posts/gitops-with-flux-cd.md","configurations/git-symlinks-setup",{"id":1324,"data":1326,"body":1334,"filePath":1335,"digest":1336,"rendered":1337,"legacyId":1389},{"title":1327,"description":1328,"pubDate":1329,"heroImage":1330,"category":1331,"tags":1332,"author":1198},"Git Symbolic Links Setup for Blog Content","A comprehensive guide to setting up Git with symbolic links for efficient content management between Obsidian and your blog codebase",["Date","2023-11-01T00:00:00.000Z"],"/images/git-symlinks-hero.jpg","Development",[510,827,1333,271],"workflow","# Git Symbolic Links Setup for Blog Content\n\n## Overview\n\nThis document explains the setup that allows the blog content to be managed in Obsidian while being properly versioned in Git. The setup uses Git hooks to automatically handle symbolic links, ensuring that actual content is committed while maintaining symbolic links for local development.\n\n## Architecture\n\n```mermaid\ngraph TD\n A[Obsidian Vault] -->|Symbolic Links| B[Blog Repository]\n B -->|Pre-commit Hook| C[Convert to Content]\n C -->|Commit| D[Git Repository]\n D -->|Post-commit Hook| E[Restore Symlinks]\n E -->|Local Development| B\n```\n\n## Directory Structure\n\n### Obsidian Content Location\n```\n/mnt/synology/obsidian/Public/Blog/\n├── posts/\n├── projects/\n├── configurations/\n├── external-posts/\n├── configs/\n├── images/\n├── infrastructure/\n└── content/\n```\n\n### Blog Repository Structure\n```\nlaforceit-blog/\n├── src/content/\n│ ├── posts -> /mnt/synology/obsidian/Public/Blog/posts\n│ ├── projects -> /mnt/synology/obsidian/Public/Blog/projects\n│ ├── configurations -> /mnt/synology/obsidian/Public/Blog/configurations\n│ └── external-posts -> /mnt/synology/obsidian/Public/Blog/external-posts\n└── public/blog/\n ├── configs -> /mnt/synology/obsidian/Public/Blog/configs\n ├── images -> /mnt/synology/obsidian/Public/Blog/images\n ├── infrastructure -> /mnt/synology/obsidian/Public/Blog/infrastructure\n └── posts -> /mnt/synology/obsidian/Public/Blog/posts\n```\n\n## Setup Instructions\n\n1. Clone the Blog Repository\n```bash\ngit clone https://git.argobox.com/KeyArgo/laforceit-blog.git\ncd laforceit-blog\n```\n\n2. Create the Scripts Directory\n```bash\nmkdir -p scripts\n```\n\n3. Create the Content Processing Script\nCreate `scripts/process-content-links.sh`:\n```bash\n#!/bin/bash\n\n# Script to handle symbolic links before commit\necho \"Processing symbolic links for content...\"\n\n# Array of content directories to process\ndeclare -A CONTENT_PATHS\n# src/content directories\nCONTENT_PATHS[\"posts\"]=\"src/content/posts\"\nCONTENT_PATHS[\"projects\"]=\"src/content/projects\"\nCONTENT_PATHS[\"configurations\"]=\"src/content/configurations\"\nCONTENT_PATHS[\"external-posts\"]=\"src/content/external-posts\"\n# public/blog directories\nCONTENT_PATHS[\"configs\"]=\"public/blog/configs\"\nCONTENT_PATHS[\"images\"]=\"public/blog/images\"\nCONTENT_PATHS[\"infrastructure\"]=\"public/blog/infrastructure\"\nCONTENT_PATHS[\"blog-posts\"]=\"public/blog/posts\"\n\nfor dir_name in \"${!CONTENT_PATHS[@]}\"; do\n dir_path=\"${CONTENT_PATHS[$dir_name]}\"\n if [ -L \"$dir_path\" ]; then\n echo \"Processing $dir_path...\"\n target=$(readlink \"$dir_path\")\n rm \"$dir_path\"\n mkdir -p \"$(dirname \"$dir_path\")\"\n cp -r \"$target\" \"$dir_path\"\n git add \"$dir_path\"\n echo \"Processed $dir_path -> $target\"\n else\n echo \"Skipping $dir_path (not a symbolic link)\"\n fi\ndone\n\necho \"Content processing complete!\"\n```\n\n4. Create Git Hooks\n\n### Pre-commit Hook\nCreate `.git/hooks/pre-commit`:\n```bash\n#!/bin/bash\n# Pre-commit hook to process symbolic links\n\necho \"Running pre-commit hook for blog content...\"\n\n# Get the absolute path to the script\nSCRIPT_PATH=\"$(git rev-parse --show-toplevel)/scripts/process-content-links.sh\"\n\n# Check if the script exists and is executable\nif [ -x \"$SCRIPT_PATH\" ]; then\n bash \"$SCRIPT_PATH\"\n # Add any new or changed files resulting from the script\n git add -A\nelse\n echo \"Error: Content processing script not found or not executable at $SCRIPT_PATH\"\n echo \"Please ensure the script exists and has execute permissions\"\n exit 1\nfi\n```\n\n### Post-commit Hook\nCreate `.git/hooks/post-commit`:\n```bash\n#!/bin/bash\n# Post-commit hook to restore symbolic links\n\necho \"Running post-commit hook to restore symbolic links...\"\n\n# Array of content directories and their targets\ndeclare -A SYMLINK_TARGETS=(\n [\"src/content/posts\"]=\"/mnt/synology/obsidian/Public/Blog/posts\"\n [\"src/content/projects\"]=\"/mnt/synology/obsidian/Public/Blog/projects\"\n [\"src/content/configurations\"]=\"/mnt/synology/obsidian/Public/Blog/configurations\"\n [\"src/content/external-posts\"]=\"/mnt/synology/obsidian/Public/Blog/external-posts\"\n [\"public/blog/configs\"]=\"/mnt/synology/obsidian/Public/Blog/configs\"\n [\"public/blog/images\"]=\"/mnt/synology/obsidian/Public/Blog/images\"\n [\"public/blog/infrastructure\"]=\"/mnt/synology/obsidian/Public/Blog/infrastructure\"\n [\"public/blog/posts\"]=\"/mnt/synology/obsidian/Public/Blog/posts\"\n)\n\nfor dir_path in \"${!SYMLINK_TARGETS[@]}\"; do\n target=\"${SYMLINK_TARGETS[$dir_path]}\"\n if [ -d \"$target\" ]; then\n echo \"Restoring symlink for $dir_path -> $target\"\n rm -rf \"$dir_path\"\n mkdir -p \"$(dirname \"$dir_path\")\"\n ln -s \"$target\" \"$dir_path\"\n else\n echo \"Warning: Target directory $target does not exist\"\n fi\ndone\n\necho \"Symbolic links restored!\"\n```\n\n5. Set Proper Permissions\n```bash\nchmod +x scripts/process-content-links.sh\nchmod +x .git/hooks/pre-commit\nchmod +x .git/hooks/post-commit\n```\n\n6. Create Symbolic Links\n```bash\n# Create necessary directories\nmkdir -p src/content public/blog\n\n# Create symbolic links for src/content\nln -s /mnt/synology/obsidian/Public/Blog/posts src/content/posts\nln -s /mnt/synology/obsidian/Public/Blog/projects src/content/projects\nln -s /mnt/synology/obsidian/Public/Blog/configurations src/content/configurations\nln -s /mnt/synology/obsidian/Public/Blog/external-posts src/content/external-posts\n\n# Create symbolic links for public/blog\nln -s /mnt/synology/obsidian/Public/Blog/configs public/blog/configs\nln -s /mnt/synology/obsidian/Public/Blog/images public/blog/images\nln -s /mnt/synology/obsidian/Public/Blog/infrastructure public/blog/infrastructure\nln -s /mnt/synology/obsidian/Public/Blog/posts public/blog/posts\n```\n\n## Git Configuration\n\n1. Configure Git to Handle Symbolic Links\n```bash\ngit config core.symlinks true\n```\n\n2. Create `.gitattributes`\n```\n# Handle symbolic links as real content\npublic/blog/* !symlink\nsrc/content/* !symlink\n\n# Treat these directories as regular directories even if they're symlinks\npublic/blog/configs/ -symlink\npublic/blog/images/ -symlink\npublic/blog/infrastructure/ -symlink\npublic/blog/posts/ -symlink\nsrc/content/posts/ -symlink\nsrc/content/projects/ -symlink\nsrc/content/configurations/ -symlink\nsrc/content/external-posts/ -symlink\n\n# Set text files to automatically normalize line endings\n* text=auto\n```\n\n## How It Works\n\n1. **Normal Development**\n - Content is edited in Obsidian\n - Blog repository uses symbolic links to this content\n - Local development works seamlessly\n\n2. **During Commits**\n - Pre-commit hook activates\n - Symbolic links are converted to actual content\n - Content is committed to the repository\n\n3. **After Commits**\n - Post-commit hook activates\n - Symbolic links are restored\n - Local development continues normally\n\n## Viewing in Gitea\n\nYes, you can view this setup in Gitea:\n1. The actual content will be visible in the repository\n2. The `.git/hooks` directory and scripts will be visible\n3. The symbolic links will appear as regular directories in Gitea\n\n## Troubleshooting\n\n1. **Symbolic Links Not Working**\n - Check file permissions\n - Verify Obsidian vault location\n - Ensure Git symlinks are enabled\n\n2. **Hooks Not Executing**\n - Check execute permissions on scripts\n - Verify hook files are in `.git/hooks`\n - Check script paths are correct\n\n3. **Content Not Committing**\n - Check Git configuration\n - Verify pre-commit hook execution\n - Check file permissions\n\n## Maintenance\n\n1. **Adding New Content Directories**\n - Add to `CONTENT_PATHS` in process-content-links.sh\n - Add to `SYMLINK_TARGETS` in post-commit hook\n - Create corresponding symbolic links\n\n2. **Changing Obsidian Location**\n - Update paths in post-commit hook\n - Update existing symbolic links\n\n3. **Backup Considerations**\n - Both Obsidian content and blog repository should be backed up\n - Keep hooks and scripts in version control\n\n## Security Notes\n\n1. Keep sensitive content outside of public blog directories\n2. Review content before commits\n3. Use `.gitignore` for private files\n4. Consider access permissions on Obsidian vault","src/content/blog/configurations/git-symlinks-setup.md","981f1ffd364b9756",{"html":1338,"metadata":1339},"\u003Ch1 id=\"git-symbolic-links-setup-for-blog-content\">Git Symbolic Links Setup for Blog Content\u003C/h1>\n\u003Ch2 id=\"overview\">Overview\u003C/h2>\n\u003Cp>This document explains the setup that allows the blog content to be managed in Obsidian while being properly versioned in Git. The setup uses Git hooks to automatically handle symbolic links, ensuring that actual content is committed while maintaining symbolic links for local development.\u003C/p>\n\u003Ch2 id=\"architecture\">Architecture\u003C/h2>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"mermaid\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">graph TD\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> A[Obsidian Vault] -->|Symbolic Links| B[Blog Repository]\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> B -->|Pre-commit Hook| C[Convert to Content]\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> C -->|Commit| D[Git Repository]\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> D -->|Post-commit Hook| E[Restore Symlinks]\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> E -->|Local Development| B\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"directory-structure\">Directory Structure\u003C/h2>\n\u003Ch3 id=\"obsidian-content-location\">Obsidian Content Location\u003C/h3>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"plaintext\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan>/mnt/synology/obsidian/Public/Blog/\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>├── posts/\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>├── projects/\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>├── configurations/\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>├── external-posts/\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>├── configs/\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>├── images/\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>├── infrastructure/\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>└── content/\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"blog-repository-structure\">Blog Repository Structure\u003C/h3>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"plaintext\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan>laforceit-blog/\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>├── src/content/\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>│ ├── posts -> /mnt/synology/obsidian/Public/Blog/posts\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>│ ├── projects -> /mnt/synology/obsidian/Public/Blog/projects\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>│ ├── configurations -> /mnt/synology/obsidian/Public/Blog/configurations\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>│ └── external-posts -> /mnt/synology/obsidian/Public/Blog/external-posts\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>└── public/blog/\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> ├── configs -> /mnt/synology/obsidian/Public/Blog/configs\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> ├── images -> /mnt/synology/obsidian/Public/Blog/images\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> ├── infrastructure -> /mnt/synology/obsidian/Public/Blog/infrastructure\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> └── posts -> /mnt/synology/obsidian/Public/Blog/posts\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"setup-instructions\">Setup Instructions\u003C/h2>\n\u003Col>\n\u003Cli>Clone the Blog Repository\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">git\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> clone\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> https://git.argobox.com/KeyArgo/laforceit-blog.git\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">cd\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> laforceit-blog\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Col start=\"2\">\n\u003Cli>Create the Scripts Directory\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">mkdir\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -p\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> scripts\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Col start=\"3\">\n\u003Cli>Create the Content Processing Script\nCreate \u003Ccode>scripts/process-content-links.sh\u003C/code>:\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\">#!/bin/bash\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Script to handle symbolic links before commit\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">echo\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Processing symbolic links for content...\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Array of content directories to process\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\">declare\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -A\u003C/span>\u003Cspan style=\"color:#BD93F9\"> CONTENT_PATHS\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># src/content directories\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">CONTENT_PATHS[\u003C/span>\u003Cspan style=\"color:#50FA7B\">\"posts\"\u003C/span>\u003Cspan style=\"color:#50FA7B\">]\u003C/span>\u003Cspan style=\"color:#F1FA8C\">=\u003C/span>\u003Cspan style=\"color:#50FA7B\">\"src/content/posts\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">CONTENT_PATHS[\u003C/span>\u003Cspan style=\"color:#50FA7B\">\"projects\"\u003C/span>\u003Cspan style=\"color:#50FA7B\">]\u003C/span>\u003Cspan style=\"color:#F1FA8C\">=\u003C/span>\u003Cspan style=\"color:#50FA7B\">\"src/content/projects\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">CONTENT_PATHS[\u003C/span>\u003Cspan style=\"color:#50FA7B\">\"configurations\"\u003C/span>\u003Cspan style=\"color:#50FA7B\">]\u003C/span>\u003Cspan style=\"color:#F1FA8C\">=\u003C/span>\u003Cspan style=\"color:#50FA7B\">\"src/content/configurations\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">CONTENT_PATHS[\u003C/span>\u003Cspan style=\"color:#50FA7B\">\"external-posts\"\u003C/span>\u003Cspan style=\"color:#50FA7B\">]\u003C/span>\u003Cspan style=\"color:#F1FA8C\">=\u003C/span>\u003Cspan style=\"color:#50FA7B\">\"src/content/external-posts\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># public/blog directories\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">CONTENT_PATHS[\u003C/span>\u003Cspan style=\"color:#50FA7B\">\"configs\"\u003C/span>\u003Cspan style=\"color:#50FA7B\">]\u003C/span>\u003Cspan style=\"color:#F1FA8C\">=\u003C/span>\u003Cspan style=\"color:#50FA7B\">\"public/blog/configs\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">CONTENT_PATHS[\u003C/span>\u003Cspan style=\"color:#50FA7B\">\"images\"\u003C/span>\u003Cspan style=\"color:#50FA7B\">]\u003C/span>\u003Cspan style=\"color:#F1FA8C\">=\u003C/span>\u003Cspan style=\"color:#50FA7B\">\"public/blog/images\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">CONTENT_PATHS[\u003C/span>\u003Cspan style=\"color:#50FA7B\">\"infrastructure\"\u003C/span>\u003Cspan style=\"color:#50FA7B\">]\u003C/span>\u003Cspan style=\"color:#F1FA8C\">=\u003C/span>\u003Cspan style=\"color:#50FA7B\">\"public/blog/infrastructure\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">CONTENT_PATHS[\u003C/span>\u003Cspan style=\"color:#50FA7B\">\"blog-posts\"\u003C/span>\u003Cspan style=\"color:#50FA7B\">]\u003C/span>\u003Cspan style=\"color:#F1FA8C\">=\u003C/span>\u003Cspan style=\"color:#50FA7B\">\"public/blog/posts\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\">for\u003C/span>\u003Cspan style=\"color:#BD93F9\"> dir_name\u003C/span>\u003Cspan style=\"color:#FF79C6\"> in\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">${\u003C/span>\u003Cspan style=\"color:#FF79C6\">!\u003C/span>\u003Cspan style=\"color:#BD93F9\">CONTENT_PATHS\u003C/span>\u003Cspan style=\"color:#F1FA8C\">[\u003C/span>\u003Cspan style=\"color:#FF79C6\">@\u003C/span>\u003Cspan style=\"color:#F1FA8C\">]}\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">; \u003C/span>\u003Cspan style=\"color:#FF79C6\">do\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> dir_path\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">${\u003C/span>\u003Cspan style=\"color:#BD93F9\">CONTENT_PATHS\u003C/span>\u003Cspan style=\"color:#F1FA8C\">[\u003C/span>\u003Cspan style=\"color:#BD93F9\">$dir_name\u003C/span>\u003Cspan style=\"color:#F1FA8C\">]}\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> if\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [ \u003C/span>\u003Cspan style=\"color:#FF79C6\">-L\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#BD93F9\">$dir_path\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> ]; \u003C/span>\u003Cspan style=\"color:#FF79C6\">then\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> echo\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Processing \u003C/span>\u003Cspan style=\"color:#BD93F9\">$dir_path\u003C/span>\u003Cspan style=\"color:#F1FA8C\">...\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> target\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#F8F8F2\">$(\u003C/span>\u003Cspan style=\"color:#50FA7B\">readlink\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#BD93F9\">$dir_path\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">)\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\"> rm\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#BD93F9\">$dir_path\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\"> mkdir\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -p\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">$(\u003C/span>\u003Cspan style=\"color:#50FA7B\">dirname\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#BD93F9\">$dir_path\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">)\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\"> cp\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -r\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#BD93F9\">$target\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#BD93F9\">$dir_path\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\"> git\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> add\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#BD93F9\">$dir_path\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> echo\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Processed \u003C/span>\u003Cspan style=\"color:#BD93F9\">$dir_path\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> -> \u003C/span>\u003Cspan style=\"color:#BD93F9\">$target\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> else\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> echo\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Skipping \u003C/span>\u003Cspan style=\"color:#BD93F9\">$dir_path\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> (not a symbolic link)\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> fi\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\">done\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">echo\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Content processing complete!\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Col start=\"4\">\n\u003Cli>Create Git Hooks\u003C/li>\n\u003C/ol>\n\u003Ch3 id=\"pre-commit-hook\">Pre-commit Hook\u003C/h3>\n\u003Cp>Create \u003Ccode>.git/hooks/pre-commit\u003C/code>:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\">#!/bin/bash\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Pre-commit hook to process symbolic links\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">echo\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Running pre-commit hook for blog content...\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Get the absolute path to the script\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\">SCRIPT_PATH\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">$(\u003C/span>\u003Cspan style=\"color:#50FA7B\">git\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> rev-parse \u003C/span>\u003Cspan style=\"color:#BD93F9\">--show-toplevel\u003C/span>\u003Cspan style=\"color:#F1FA8C\">)/scripts/process-content-links.sh\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Check if the script exists and is executable\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\">if\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [ \u003C/span>\u003Cspan style=\"color:#FF79C6\">-x\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#BD93F9\">$SCRIPT_PATH\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> ]; \u003C/span>\u003Cspan style=\"color:#FF79C6\">then\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\"> bash\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#BD93F9\">$SCRIPT_PATH\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> # Add any new or changed files resulting from the script\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\"> git\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> add\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -A\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\">else\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> echo\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Error: Content processing script not found or not executable at \u003C/span>\u003Cspan style=\"color:#BD93F9\">$SCRIPT_PATH\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> echo\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Please ensure the script exists and has execute permissions\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> exit\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\">fi\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"post-commit-hook\">Post-commit Hook\u003C/h3>\n\u003Cp>Create \u003Ccode>.git/hooks/post-commit\u003C/code>:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\">#!/bin/bash\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Post-commit hook to restore symbolic links\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">echo\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Running post-commit hook to restore symbolic links...\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Array of content directories and their targets\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\">declare\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -A\u003C/span>\u003Cspan style=\"color:#BD93F9\"> SYMLINK_TARGETS\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#F8F8F2\">(\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\">\"src/content/posts\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">]=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">/mnt/synology/obsidian/Public/Blog/posts\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\">\"src/content/projects\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">]=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">/mnt/synology/obsidian/Public/Blog/projects\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\">\"src/content/configurations\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">]=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">/mnt/synology/obsidian/Public/Blog/configurations\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\">\"src/content/external-posts\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">]=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">/mnt/synology/obsidian/Public/Blog/external-posts\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\">\"public/blog/configs\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">]=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">/mnt/synology/obsidian/Public/Blog/configs\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\">\"public/blog/images\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">]=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">/mnt/synology/obsidian/Public/Blog/images\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\">\"public/blog/infrastructure\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">]=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">/mnt/synology/obsidian/Public/Blog/infrastructure\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\">\"public/blog/posts\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">]=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">/mnt/synology/obsidian/Public/Blog/posts\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">)\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\">for\u003C/span>\u003Cspan style=\"color:#BD93F9\"> dir_path\u003C/span>\u003Cspan style=\"color:#FF79C6\"> in\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">${\u003C/span>\u003Cspan style=\"color:#FF79C6\">!\u003C/span>\u003Cspan style=\"color:#BD93F9\">SYMLINK_TARGETS\u003C/span>\u003Cspan style=\"color:#F1FA8C\">[\u003C/span>\u003Cspan style=\"color:#FF79C6\">@\u003C/span>\u003Cspan style=\"color:#F1FA8C\">]}\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">; \u003C/span>\u003Cspan style=\"color:#FF79C6\">do\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> target\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">${\u003C/span>\u003Cspan style=\"color:#BD93F9\">SYMLINK_TARGETS\u003C/span>\u003Cspan style=\"color:#F1FA8C\">[\u003C/span>\u003Cspan style=\"color:#BD93F9\">$dir_path\u003C/span>\u003Cspan style=\"color:#F1FA8C\">]}\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> if\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [ \u003C/span>\u003Cspan style=\"color:#FF79C6\">-d\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#BD93F9\">$target\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> ]; \u003C/span>\u003Cspan style=\"color:#FF79C6\">then\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> echo\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Restoring symlink for \u003C/span>\u003Cspan style=\"color:#BD93F9\">$dir_path\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> -> \u003C/span>\u003Cspan style=\"color:#BD93F9\">$target\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\"> rm\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -rf\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#BD93F9\">$dir_path\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\"> mkdir\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -p\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">$(\u003C/span>\u003Cspan style=\"color:#50FA7B\">dirname\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#BD93F9\">$dir_path\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">)\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\"> ln\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -s\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#BD93F9\">$target\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#BD93F9\">$dir_path\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> else\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> echo\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Warning: Target directory \u003C/span>\u003Cspan style=\"color:#BD93F9\">$target\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> does not exist\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> fi\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\">done\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">echo\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Symbolic links restored!\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Col start=\"5\">\n\u003Cli>Set Proper Permissions\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">chmod\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> +x\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> scripts/process-content-links.sh\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">chmod\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> +x\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> .git/hooks/pre-commit\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">chmod\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> +x\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> .git/hooks/post-commit\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Col start=\"6\">\n\u003Cli>Create Symbolic Links\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Create necessary directories\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">mkdir\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -p\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> src/content\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> public/blog\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Create symbolic links for src/content\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">ln\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -s\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /mnt/synology/obsidian/Public/Blog/posts\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> src/content/posts\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">ln\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -s\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /mnt/synology/obsidian/Public/Blog/projects\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> src/content/projects\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">ln\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -s\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /mnt/synology/obsidian/Public/Blog/configurations\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> src/content/configurations\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">ln\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -s\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /mnt/synology/obsidian/Public/Blog/external-posts\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> src/content/external-posts\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Create symbolic links for public/blog\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">ln\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -s\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /mnt/synology/obsidian/Public/Blog/configs\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> public/blog/configs\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">ln\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -s\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /mnt/synology/obsidian/Public/Blog/images\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> public/blog/images\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">ln\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -s\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /mnt/synology/obsidian/Public/Blog/infrastructure\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> public/blog/infrastructure\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">ln\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -s\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /mnt/synology/obsidian/Public/Blog/posts\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> public/blog/posts\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"git-configuration\">Git Configuration\u003C/h2>\n\u003Col>\n\u003Cli>Configure Git to Handle Symbolic Links\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">git\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> config\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> core.symlinks\u003C/span>\u003Cspan style=\"color:#BD93F9\"> true\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Col start=\"2\">\n\u003Cli>Create \u003Ccode>.gitattributes\u003C/code>\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"plaintext\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan># Handle symbolic links as real content\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>public/blog/* !symlink\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>src/content/* !symlink\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan># Treat these directories as regular directories even if they're symlinks\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>public/blog/configs/ -symlink\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>public/blog/images/ -symlink\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>public/blog/infrastructure/ -symlink\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>public/blog/posts/ -symlink\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>src/content/posts/ -symlink\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>src/content/projects/ -symlink\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>src/content/configurations/ -symlink\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>src/content/external-posts/ -symlink\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan># Set text files to automatically normalize line endings\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>* text=auto\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"how-it-works\">How It Works\u003C/h2>\n\u003Col>\n\u003Cli>\n\u003Cp>\u003Cstrong>Normal Development\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Content is edited in Obsidian\u003C/li>\n\u003Cli>Blog repository uses symbolic links to this content\u003C/li>\n\u003Cli>Local development works seamlessly\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>During Commits\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Pre-commit hook activates\u003C/li>\n\u003Cli>Symbolic links are converted to actual content\u003C/li>\n\u003Cli>Content is committed to the repository\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>After Commits\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Post-commit hook activates\u003C/li>\n\u003Cli>Symbolic links are restored\u003C/li>\n\u003Cli>Local development continues normally\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003C/ol>\n\u003Ch2 id=\"viewing-in-gitea\">Viewing in Gitea\u003C/h2>\n\u003Cp>Yes, you can view this setup in Gitea:\u003C/p>\n\u003Col>\n\u003Cli>The actual content will be visible in the repository\u003C/li>\n\u003Cli>The \u003Ccode>.git/hooks\u003C/code> directory and scripts will be visible\u003C/li>\n\u003Cli>The symbolic links will appear as regular directories in Gitea\u003C/li>\n\u003C/ol>\n\u003Ch2 id=\"troubleshooting\">Troubleshooting\u003C/h2>\n\u003Col>\n\u003Cli>\n\u003Cp>\u003Cstrong>Symbolic Links Not Working\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Check file permissions\u003C/li>\n\u003Cli>Verify Obsidian vault location\u003C/li>\n\u003Cli>Ensure Git symlinks are enabled\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>Hooks Not Executing\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Check execute permissions on scripts\u003C/li>\n\u003Cli>Verify hook files are in \u003Ccode>.git/hooks\u003C/code>\u003C/li>\n\u003Cli>Check script paths are correct\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>Content Not Committing\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Check Git configuration\u003C/li>\n\u003Cli>Verify pre-commit hook execution\u003C/li>\n\u003Cli>Check file permissions\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003C/ol>\n\u003Ch2 id=\"maintenance\">Maintenance\u003C/h2>\n\u003Col>\n\u003Cli>\n\u003Cp>\u003Cstrong>Adding New Content Directories\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Add to \u003Ccode>CONTENT_PATHS\u003C/code> in process-content-links.sh\u003C/li>\n\u003Cli>Add to \u003Ccode>SYMLINK_TARGETS\u003C/code> in post-commit hook\u003C/li>\n\u003Cli>Create corresponding symbolic links\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>Changing Obsidian Location\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Update paths in post-commit hook\u003C/li>\n\u003Cli>Update existing symbolic links\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>Backup Considerations\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>Both Obsidian content and blog repository should be backed up\u003C/li>\n\u003Cli>Keep hooks and scripts in version control\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003C/ol>\n\u003Ch2 id=\"security-notes\">Security Notes\u003C/h2>\n\u003Col>\n\u003Cli>Keep sensitive content outside of public blog directories\u003C/li>\n\u003Cli>Review content before commits\u003C/li>\n\u003Cli>Use \u003Ccode>.gitignore\u003C/code> for private files\u003C/li>\n\u003Cli>Consider access permissions on Obsidian vault\u003C/li>\n\u003C/ol>",{"headings":1340,"localImagePaths":1383,"remoteImagePaths":1384,"frontmatter":1385,"imagePaths":1388},[1341,1343,1346,1349,1352,1355,1358,1361,1364,1367,1370,1373,1376,1377,1380],{"depth":52,"slug":1342,"text":1327},"git-symbolic-links-setup-for-blog-content",{"depth":55,"slug":1344,"text":1345},"overview","Overview",{"depth":55,"slug":1347,"text":1348},"architecture","Architecture",{"depth":55,"slug":1350,"text":1351},"directory-structure","Directory Structure",{"depth":97,"slug":1353,"text":1354},"obsidian-content-location","Obsidian Content Location",{"depth":97,"slug":1356,"text":1357},"blog-repository-structure","Blog Repository Structure",{"depth":55,"slug":1359,"text":1360},"setup-instructions","Setup Instructions",{"depth":97,"slug":1362,"text":1363},"pre-commit-hook","Pre-commit Hook",{"depth":97,"slug":1365,"text":1366},"post-commit-hook","Post-commit Hook",{"depth":55,"slug":1368,"text":1369},"git-configuration","Git Configuration",{"depth":55,"slug":1371,"text":1372},"how-it-works","How It Works",{"depth":55,"slug":1374,"text":1375},"viewing-in-gitea","Viewing in Gitea",{"depth":55,"slug":364,"text":365},{"depth":55,"slug":1378,"text":1379},"maintenance","Maintenance",{"depth":55,"slug":1381,"text":1382},"security-notes","Security Notes",[],[],{"title":1327,"pubDate":1386,"description":1328,"author":1198,"heroImage":1330,"category":1331,"tags":1387},["Date","2023-11-01T00:00:00.000Z"],[510,827,1333,271],[],"configurations/git-symlinks-setup.md","posts/cloudflare-tunnel-setup",{"id":1390,"data":1392,"body":384,"filePath":1395,"digest":386,"rendered":1396,"legacyId":1421},{"title":14,"description":15,"pubDate":1393,"heroImage":17,"category":18,"tags":1394,"readTime":24},["Date","2025-04-19T00:00:00.000Z"],[20,18,21,22,23],"src/content/blog/posts/cloudflare-tunnel-setup.md",{"html":388,"metadata":1397},{"headings":1398,"localImagePaths":1415,"remoteImagePaths":1416,"frontmatter":1417,"imagePaths":1420},[1399,1400,1401,1402,1403,1404,1405,1406,1407,1408,1409,1410,1411,1412,1413,1414],{"depth":52,"slug":392,"text":14},{"depth":55,"slug":394,"text":395},{"depth":55,"slug":193,"text":194},{"depth":55,"slug":398,"text":399},{"depth":97,"slug":401,"text":402},{"depth":97,"slug":404,"text":405},{"depth":97,"slug":407,"text":408},{"depth":97,"slug":410,"text":411},{"depth":97,"slug":413,"text":414},{"depth":97,"slug":416,"text":417},{"depth":55,"slug":419,"text":420},{"depth":55,"slug":422,"text":423},{"depth":55,"slug":361,"text":362},{"depth":97,"slug":426,"text":427},{"depth":97,"slug":429,"text":430},{"depth":55,"slug":162,"text":163},[],[],{"title":14,"description":15,"pubDate":1418,"heroImage":17,"category":18,"tags":1419,"readTime":24},["Date","2025-04-19T00:00:00.000Z"],[20,18,21,22,23],[],"posts/cloudflare-tunnel-setup.md","posts/prometheus-monitoring",{"id":1422,"data":1424,"body":1430,"filePath":1431,"digest":1432,"rendered":1433,"legacyId":1497},{"title":1425,"description":1426,"pubDate":1427,"heroImage":17,"category":266,"tags":1428,"readTime":1429},"Setting Up Prometheus Monitoring in Kubernetes","A comprehensive guide to implementing Prometheus monitoring in your Kubernetes cluster",["Date","2025-04-19T00:00:00.000Z"],[180,323,321,322,324],"9 min read","# Setting Up Prometheus Monitoring in Kubernetes\n\nEffective monitoring is crucial for maintaining a healthy Kubernetes environment. Prometheus has become the de facto standard for metrics collection and alerting in cloud-native environments. This guide will walk you through setting up a complete Prometheus monitoring stack in your Kubernetes cluster.\n\n## Why Prometheus?\n\nPrometheus offers several advantages for Kubernetes monitoring:\n\n- **Pull-based architecture**: Simplifies configuration and security\n- **Powerful query language (PromQL)**: For flexible data analysis\n- **Service discovery**: Automatically finds targets in dynamic environments\n- **Rich ecosystem**: Wide range of exporters and integrations\n- **CNCF graduated project**: Strong community and vendor support\n\n## Components of the Monitoring Stack\n\nWe'll set up a complete monitoring stack consisting of:\n\n1. **Prometheus**: Core metrics collection and storage\n2. **Alertmanager**: Handles alerts and notifications\n3. **Grafana**: Visualization and dashboards\n4. **Node Exporter**: Collects host-level metrics\n5. **kube-state-metrics**: Collects Kubernetes state metrics\n6. **Prometheus Operator**: Simplifies Prometheus management in Kubernetes\n\n## Prerequisites\n\n- A running Kubernetes cluster (K3s, EKS, GKE, etc.)\n- kubectl configured to access your cluster\n- Helm 3 installed\n\n## Installation Using Helm\n\nThe easiest way to deploy Prometheus is using the kube-prometheus-stack Helm chart, which includes all the components mentioned above.\n\n### 1. Add the Prometheus Community Helm Repository\n\n```bash\nhelm repo add prometheus-community https://prometheus-community.github.io/helm-charts\nhelm repo update\n```\n\n### 2. Create a Namespace for Monitoring\n\n```bash\nkubectl create namespace monitoring\n```\n\n### 3. Configure Values\n\nCreate a `values.yaml` file with your custom configuration:\n\n```yaml\nprometheus:\n prometheusSpec:\n retention: 15d\n resources:\n requests:\n memory: 256Mi\n cpu: 100m\n limits:\n memory: 2Gi\n cpu: 500m\n storageSpec:\n volumeClaimTemplate:\n spec:\n storageClassName: standard\n accessModes: [\"ReadWriteOnce\"]\n resources:\n requests:\n storage: 20Gi\n\nalertmanager:\n alertmanagerSpec:\n storage:\n volumeClaimTemplate:\n spec:\n storageClassName: standard\n accessModes: [\"ReadWriteOnce\"]\n resources:\n requests:\n storage: 10Gi\n\ngrafana:\n persistence:\n enabled: true\n storageClassName: standard\n size: 10Gi\n adminPassword: \"prom-operator\" # Change this!\n \nnodeExporter:\n enabled: true\n\nkubeStateMetrics:\n enabled: true\n```\n\n### 4. Install the Helm Chart\n\n```bash\nhelm install prometheus prometheus-community/kube-prometheus-stack \\\n --namespace monitoring \\\n --values values.yaml\n```\n\n### 5. Verify the Installation\n\nCheck that all the pods are running:\n\n```bash\nkubectl get pods -n monitoring\n```\n\n## Accessing the UIs\n\nBy default, the components don't have external access. You can use port-forwarding to access them:\n\n### Prometheus UI\n\n```bash\nkubectl port-forward -n monitoring svc/prometheus-operated 9090:9090\n```\n\nThen access Prometheus at http://localhost:9090\n\n### Grafana\n\n```bash\nkubectl port-forward -n monitoring svc/prometheus-grafana 3000:80\n```\n\nThen access Grafana at http://localhost:3000 (default credentials: admin/prom-operator)\n\n### Alertmanager\n\n```bash\nkubectl port-forward -n monitoring svc/prometheus-alertmanager 9093:9093\n```\n\nThen access Alertmanager at http://localhost:9093\n\n## For Production: Exposing Services\n\nFor production environments, you'll want to set up proper ingress. Here's an example using a basic Ingress resource:\n\n```yaml\napiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n name: prometheus-ingress\n namespace: monitoring\n annotations:\n nginx.ingress.kubernetes.io/ssl-redirect: \"true\"\nspec:\n rules:\n - host: prometheus.example.com\n http:\n paths:\n - path: /\n pathType: Prefix\n backend:\n service:\n name: prometheus-operated\n port:\n number: 9090\n - host: grafana.example.com\n http:\n paths:\n - path: /\n pathType: Prefix\n backend:\n service:\n name: prometheus-grafana\n port:\n number: 80\n - host: alertmanager.example.com\n http:\n paths:\n - path: /\n pathType: Prefix\n backend:\n service:\n name: prometheus-alertmanager\n port:\n number: 9093\n```\n\n## Configuring Alerting\n\n### 1. Set Up Alert Rules\n\nAlert rules can be created using the PrometheusRule custom resource:\n\n```yaml\napiVersion: monitoring.coreos.com/v1\nkind: PrometheusRule\nmetadata:\n name: node-alerts\n namespace: monitoring\n labels:\n release: prometheus\nspec:\n groups:\n - name: node.rules\n rules:\n - alert: HighNodeCPU\n expr: instance:node_cpu_utilisation:rate1m > 0.8\n for: 5m\n labels:\n severity: warning\n annotations:\n summary: \"High CPU usage on {{ $labels.instance }}\"\n description: \"CPU usage is above 80% for 5 minutes on node {{ $labels.instance }}\"\n```\n\n### 2. Configure Alert Receivers\n\nConfigure Alertmanager to send notifications by creating a Secret with your configuration:\n\n```yaml\napiVersion: v1\nkind: Secret\nmetadata:\n name: alertmanager-prometheus-alertmanager\n namespace: monitoring\nstringData:\n alertmanager.yaml: |\n global:\n resolve_timeout: 5m\n slack_api_url: 'https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK'\n \n route:\n group_by: ['job', 'alertname', 'namespace']\n group_wait: 30s\n group_interval: 5m\n repeat_interval: 12h\n receiver: 'slack-notifications'\n routes:\n - receiver: 'slack-notifications'\n matchers:\n - severity =~ \"warning|critical\"\n \n receivers:\n - name: 'slack-notifications'\n slack_configs:\n - channel: '#alerts'\n send_resolved: true\n title: '{{ template \"slack.default.title\" . }}'\n text: '{{ template \"slack.default.text\" . }}'\ntype: Opaque\n```\n\n## Custom Dashboards\n\nGrafana comes pre-configured with several useful dashboards, but you can import more from [Grafana.com](https://grafana.com/grafana/dashboards/).\n\nSome recommended dashboard IDs to import:\n- 1860: Node Exporter Full\n- 12740: Kubernetes Monitoring\n- 13332: Prometheus Stats\n\n## Troubleshooting\n\n### Common Issues\n\n1. **Insufficient Resources**: Prometheus can be resource-intensive. Adjust resource limits if pods are being OOMKilled.\n2. **Storage Issues**: Ensure your storage class supports the access modes you've configured.\n3. **ServiceMonitor not working**: Check that the label selectors match your services.\n\n## Conclusion\n\nYou now have a fully functional Prometheus monitoring stack for your Kubernetes cluster. This setup provides comprehensive metrics collection, visualization, and alerting capabilities essential for maintaining a healthy and performant cluster.\n\nIn future articles, we'll explore advanced topics like custom exporters, recording rules for performance, and integrating with other observability tools like Loki for logs and Tempo for traces.","src/content/blog/posts/prometheus-monitoring.md","a28154bc8e5fceca",{"html":1434,"metadata":1435},"\u003Ch1 id=\"setting-up-prometheus-monitoring-in-kubernetes\">Setting Up Prometheus Monitoring in Kubernetes\u003C/h1>\n\u003Cp>Effective monitoring is crucial for maintaining a healthy Kubernetes environment. Prometheus has become the de facto standard for metrics collection and alerting in cloud-native environments. This guide will walk you through setting up a complete Prometheus monitoring stack in your Kubernetes cluster.\u003C/p>\n\u003Ch2 id=\"why-prometheus\">Why Prometheus?\u003C/h2>\n\u003Cp>Prometheus offers several advantages for Kubernetes monitoring:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Cstrong>Pull-based architecture\u003C/strong>: Simplifies configuration and security\u003C/li>\n\u003Cli>\u003Cstrong>Powerful query language (PromQL)\u003C/strong>: For flexible data analysis\u003C/li>\n\u003Cli>\u003Cstrong>Service discovery\u003C/strong>: Automatically finds targets in dynamic environments\u003C/li>\n\u003Cli>\u003Cstrong>Rich ecosystem\u003C/strong>: Wide range of exporters and integrations\u003C/li>\n\u003Cli>\u003Cstrong>CNCF graduated project\u003C/strong>: Strong community and vendor support\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"components-of-the-monitoring-stack\">Components of the Monitoring Stack\u003C/h2>\n\u003Cp>We’ll set up a complete monitoring stack consisting of:\u003C/p>\n\u003Col>\n\u003Cli>\u003Cstrong>Prometheus\u003C/strong>: Core metrics collection and storage\u003C/li>\n\u003Cli>\u003Cstrong>Alertmanager\u003C/strong>: Handles alerts and notifications\u003C/li>\n\u003Cli>\u003Cstrong>Grafana\u003C/strong>: Visualization and dashboards\u003C/li>\n\u003Cli>\u003Cstrong>Node Exporter\u003C/strong>: Collects host-level metrics\u003C/li>\n\u003Cli>\u003Cstrong>kube-state-metrics\u003C/strong>: Collects Kubernetes state metrics\u003C/li>\n\u003Cli>\u003Cstrong>Prometheus Operator\u003C/strong>: Simplifies Prometheus management in Kubernetes\u003C/li>\n\u003C/ol>\n\u003Ch2 id=\"prerequisites\">Prerequisites\u003C/h2>\n\u003Cul>\n\u003Cli>A running Kubernetes cluster (K3s, EKS, GKE, etc.)\u003C/li>\n\u003Cli>kubectl configured to access your cluster\u003C/li>\n\u003Cli>Helm 3 installed\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"installation-using-helm\">Installation Using Helm\u003C/h2>\n\u003Cp>The easiest way to deploy Prometheus is using the kube-prometheus-stack Helm chart, which includes all the components mentioned above.\u003C/p>\n\u003Ch3 id=\"1-add-the-prometheus-community-helm-repository\">1. Add the Prometheus Community Helm Repository\u003C/h3>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">helm\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> repo\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> add\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> prometheus-community\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> https://prometheus-community.github.io/helm-charts\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">helm\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> repo\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> update\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"2-create-a-namespace-for-monitoring\">2. Create a Namespace for Monitoring\u003C/h3>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">kubectl\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> create\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> namespace\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> monitoring\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"3-configure-values\">3. Configure Values\u003C/h3>\n\u003Cp>Create a \u003Ccode>values.yaml\u003C/code> file with your custom configuration:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">prometheus\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> prometheusSpec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> retention\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 15d\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> resources\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> requests\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> memory\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 256Mi\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> cpu\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 100m\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> limits\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> memory\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 2Gi\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> cpu\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 500m\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> storageSpec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> volumeClaimTemplate\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> storageClassName\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> standard\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> accessModes\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">ReadWriteOnce\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">]\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> resources\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> requests\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> storage\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 20Gi\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">alertmanager\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> alertmanagerSpec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> storage\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> volumeClaimTemplate\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> storageClassName\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> standard\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> accessModes\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">ReadWriteOnce\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">]\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> resources\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> requests\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> storage\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 10Gi\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">grafana\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> persistence\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> enabled\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> true\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> storageClassName\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> standard\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> size\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 10Gi\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> adminPassword\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">prom-operator\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#6272A4\"> # Change this!\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">nodeExporter\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> enabled\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> true\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">kubeStateMetrics\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> enabled\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> true\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"4-install-the-helm-chart\">4. Install the Helm Chart\u003C/h3>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">helm\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> install\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> prometheus\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> prometheus-community/kube-prometheus-stack\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> --namespace\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> monitoring\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> --values\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> values.yaml\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"5-verify-the-installation\">5. Verify the Installation\u003C/h3>\n\u003Cp>Check that all the pods are running:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">kubectl\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> get\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> pods\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -n\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> monitoring\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"accessing-the-uis\">Accessing the UIs\u003C/h2>\n\u003Cp>By default, the components don’t have external access. You can use port-forwarding to access them:\u003C/p>\n\u003Ch3 id=\"prometheus-ui\">Prometheus UI\u003C/h3>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">kubectl\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> port-forward\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -n\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> monitoring\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> svc/prometheus-operated\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 9090:9090\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Then access Prometheus at \u003Ca href=\"http://localhost:9090\">http://localhost:9090\u003C/a>\u003C/p>\n\u003Ch3 id=\"grafana\">Grafana\u003C/h3>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">kubectl\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> port-forward\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -n\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> monitoring\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> svc/prometheus-grafana\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 3000:80\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Then access Grafana at \u003Ca href=\"http://localhost:3000\">http://localhost:3000\u003C/a> (default credentials: admin/prom-operator)\u003C/p>\n\u003Ch3 id=\"alertmanager\">Alertmanager\u003C/h3>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">kubectl\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> port-forward\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -n\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> monitoring\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> svc/prometheus-alertmanager\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 9093:9093\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Then access Alertmanager at \u003Ca href=\"http://localhost:9093\">http://localhost:9093\u003C/a>\u003C/p>\n\u003Ch2 id=\"for-production-exposing-services\">For Production: Exposing Services\u003C/h2>\n\u003Cp>For production environments, you’ll want to set up proper ingress. Here’s an example using a basic Ingress resource:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">apiVersion\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> networking.k8s.io/v1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">kind\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Ingress\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">metadata\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> prometheus-ingress\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> namespace\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> monitoring\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> annotations\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> nginx.ingress.kubernetes.io/ssl-redirect\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">true\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> rules\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> host\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> prometheus.example.com\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> http\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> paths\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> path\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> pathType\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Prefix\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> backend\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> service\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> prometheus-operated\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> port\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> number\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 9090\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> host\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> grafana.example.com\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> http\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> paths\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> path\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> pathType\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Prefix\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> backend\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> service\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> prometheus-grafana\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> port\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> number\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 80\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> host\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> alertmanager.example.com\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> http\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> paths\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> path\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> pathType\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Prefix\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> backend\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> service\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> prometheus-alertmanager\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> port\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> number\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 9093\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"configuring-alerting\">Configuring Alerting\u003C/h2>\n\u003Ch3 id=\"1-set-up-alert-rules\">1. Set Up Alert Rules\u003C/h3>\n\u003Cp>Alert rules can be created using the PrometheusRule custom resource:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">apiVersion\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> monitoring.coreos.com/v1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">kind\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> PrometheusRule\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">metadata\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> node-alerts\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> namespace\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> monitoring\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> labels\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> release\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> prometheus\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> groups\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> node.rules\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> rules\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> alert\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> HighNodeCPU\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> expr\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> instance:node_cpu_utilisation:rate1m > 0.8\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> for\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 5m\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> labels\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> severity\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> warning\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> annotations\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> summary\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">High CPU usage on {{ $labels.instance }}\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> description\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">CPU usage is above 80% for 5 minutes on node {{ $labels.instance }}\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"2-configure-alert-receivers\">2. Configure Alert Receivers\u003C/h3>\n\u003Cp>Configure Alertmanager to send notifications by creating a Secret with your configuration:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">apiVersion\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> v1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">kind\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Secret\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">metadata\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> alertmanager-prometheus-alertmanager\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> namespace\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> monitoring\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">stringData\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> alertmanager.yaml\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#FF79C6\"> |\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> global:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> resolve_timeout: 5m\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> slack_api_url: 'https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> route:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> group_by: ['job', 'alertname', 'namespace']\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> group_wait: 30s\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> group_interval: 5m\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> repeat_interval: 12h\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> receiver: 'slack-notifications'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> routes:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> - receiver: 'slack-notifications'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> matchers:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> - severity =~ \"warning|critical\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> receivers:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> - name: 'slack-notifications'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> slack_configs:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> - channel: '#alerts'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> send_resolved: true\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> title: '{{ template \"slack.default.title\" . }}'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> text: '{{ template \"slack.default.text\" . }}'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">type\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Opaque\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"custom-dashboards\">Custom Dashboards\u003C/h2>\n\u003Cp>Grafana comes pre-configured with several useful dashboards, but you can import more from \u003Ca href=\"https://grafana.com/grafana/dashboards/\">Grafana.com\u003C/a>.\u003C/p>\n\u003Cp>Some recommended dashboard IDs to import:\u003C/p>\n\u003Cul>\n\u003Cli>1860: Node Exporter Full\u003C/li>\n\u003Cli>12740: Kubernetes Monitoring\u003C/li>\n\u003Cli>13332: Prometheus Stats\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"troubleshooting\">Troubleshooting\u003C/h2>\n\u003Ch3 id=\"common-issues\">Common Issues\u003C/h3>\n\u003Col>\n\u003Cli>\u003Cstrong>Insufficient Resources\u003C/strong>: Prometheus can be resource-intensive. Adjust resource limits if pods are being OOMKilled.\u003C/li>\n\u003Cli>\u003Cstrong>Storage Issues\u003C/strong>: Ensure your storage class supports the access modes you’ve configured.\u003C/li>\n\u003Cli>\u003Cstrong>ServiceMonitor not working\u003C/strong>: Check that the label selectors match your services.\u003C/li>\n\u003C/ol>\n\u003Ch2 id=\"conclusion\">Conclusion\u003C/h2>\n\u003Cp>You now have a fully functional Prometheus monitoring stack for your Kubernetes cluster. This setup provides comprehensive metrics collection, visualization, and alerting capabilities essential for maintaining a healthy and performant cluster.\u003C/p>\n\u003Cp>In future articles, we’ll explore advanced topics like custom exporters, recording rules for performance, and integrating with other observability tools like Loki for logs and Tempo for traces.\u003C/p>",{"headings":1436,"localImagePaths":1491,"remoteImagePaths":1492,"frontmatter":1493,"imagePaths":1496},[1437,1439,1442,1445,1446,1448,1451,1454,1457,1460,1463,1466,1469,1470,1473,1476,1479,1482,1485,1488,1489,1490],{"depth":52,"slug":1438,"text":1425},"setting-up-prometheus-monitoring-in-kubernetes",{"depth":55,"slug":1440,"text":1441},"why-prometheus","Why Prometheus?",{"depth":55,"slug":1443,"text":1444},"components-of-the-monitoring-stack","Components of the Monitoring Stack",{"depth":55,"slug":193,"text":194},{"depth":55,"slug":339,"text":1447},"Installation Using Helm",{"depth":97,"slug":1449,"text":1450},"1-add-the-prometheus-community-helm-repository","1. Add the Prometheus Community Helm Repository",{"depth":97,"slug":1452,"text":1453},"2-create-a-namespace-for-monitoring","2. Create a Namespace for Monitoring",{"depth":97,"slug":1455,"text":1456},"3-configure-values","3. Configure Values",{"depth":97,"slug":1458,"text":1459},"4-install-the-helm-chart","4. Install the Helm Chart",{"depth":97,"slug":1461,"text":1462},"5-verify-the-installation","5. Verify the Installation",{"depth":55,"slug":1464,"text":1465},"accessing-the-uis","Accessing the UIs",{"depth":97,"slug":1467,"text":1468},"prometheus-ui","Prometheus UI",{"depth":97,"slug":322,"text":345},{"depth":97,"slug":1471,"text":1472},"alertmanager","Alertmanager",{"depth":55,"slug":1474,"text":1475},"for-production-exposing-services","For Production: Exposing Services",{"depth":55,"slug":1477,"text":1478},"configuring-alerting","Configuring Alerting",{"depth":97,"slug":1480,"text":1481},"1-set-up-alert-rules","1. Set Up Alert Rules",{"depth":97,"slug":1483,"text":1484},"2-configure-alert-receivers","2. Configure Alert Receivers",{"depth":55,"slug":1486,"text":1487},"custom-dashboards","Custom Dashboards",{"depth":55,"slug":364,"text":365},{"depth":97,"slug":367,"text":368},{"depth":55,"slug":162,"text":163},[],[],{"title":1425,"description":1426,"pubDate":1494,"heroImage":17,"category":266,"tags":1495,"readTime":1429},["Date","2025-04-19T00:00:00.000Z"],[180,323,321,322,324],[],"posts/prometheus-monitoring.md","posts/filebrowser-setup",{"id":1498,"data":1500,"body":584,"filePath":1504,"digest":586,"rendered":1505,"legacyId":1525},{"title":576,"description":577,"pubDate":1501,"updatedDate":1502,"heroImage":17,"category":507,"tags":1503},["Date","2025-04-19T00:00:00.000Z"],["Date","2025-04-18T00:00:00.000Z"],[581,511,180,582,583],"src/content/blog/posts/filebrowser-setup.md",{"html":588,"metadata":1506},{"headings":1507,"localImagePaths":1518,"remoteImagePaths":1519,"frontmatter":1520,"imagePaths":1524},[1508,1509,1510,1511,1512,1513,1514,1515,1516,1517],{"depth":55,"slug":592,"text":593},{"depth":55,"slug":595,"text":596},{"depth":97,"slug":598,"text":599},{"depth":97,"slug":601,"text":602},{"depth":55,"slug":604,"text":605},{"depth":97,"slug":607,"text":608},{"depth":55,"slug":610,"text":611},{"depth":55,"slug":613,"text":614},{"depth":55,"slug":616,"text":617},{"depth":55,"slug":563,"text":564},[],[],{"title":576,"description":577,"pubDate":1521,"updatedDate":1522,"category":507,"tags":1523,"heroImage":17},["Date","2025-04-19T00:00:00.000Z"],["Date","2025-04-18T00:00:00.000Z"],[581,511,180,582,583],[],"posts/filebrowser-setup.md","posts/gitea-self-hosted-git",{"id":1526,"data":1528,"body":512,"filePath":1532,"digest":514,"rendered":1533,"legacyId":1559},{"title":503,"description":504,"pubDate":1529,"updatedDate":1530,"heroImage":17,"category":507,"tags":1531},["Date","2025-04-19T00:00:00.000Z"],["Date","2025-04-18T00:00:00.000Z"],[509,510,511,266,180],"src/content/blog/posts/gitea-self-hosted-git.md",{"html":516,"metadata":1534},{"headings":1535,"localImagePaths":1552,"remoteImagePaths":1553,"frontmatter":1554,"imagePaths":1558},[1536,1537,1538,1539,1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550,1551],{"depth":55,"slug":520,"text":521},{"depth":55,"slug":523,"text":524},{"depth":97,"slug":526,"text":527},{"depth":97,"slug":529,"text":530},{"depth":55,"slug":532,"text":533},{"depth":55,"slug":535,"text":536},{"depth":97,"slug":538,"text":539},{"depth":97,"slug":541,"text":542},{"depth":97,"slug":544,"text":545},{"depth":55,"slug":547,"text":548},{"depth":97,"slug":550,"text":551},{"depth":97,"slug":553,"text":554},{"depth":97,"slug":556,"text":557},{"depth":55,"slug":422,"text":423},{"depth":55,"slug":560,"text":561},{"depth":55,"slug":563,"text":564},[],[],{"title":503,"description":504,"pubDate":1555,"updatedDate":1556,"category":507,"tags":1557,"heroImage":17},["Date","2025-04-19T00:00:00.000Z"],["Date","2025-04-18T00:00:00.000Z"],[509,510,511,266,180],[],"posts/gitea-self-hosted-git.md","posts/starting-my-digital-garden",{"id":1560,"data":1562,"body":1566,"filePath":1567,"digest":1568,"rendered":1569,"legacyId":1591},{"title":442,"pubDate":1563,"heroImage":17,"tags":1564,"draft":182},["Date","2025-04-19T00:00:00.000Z"],[9,1565,448],"meta","# Starting My Digital Garden\n\n## Introduction\n\nToday I'm launching my public digital garden - a space where I'll share my thoughts, ideas, and projects with the world.\n\n## What to Expect\n\nThis site contains two main sections:\n\n1. **Journal** - Daily notes and thoughts, more raw and in-the-moment\n2. **Blog** - More structured and polished articles on various topics\n\nI'll be using my daily journal to capture ideas as they happen, and some of these will evolve into more detailed blog posts over time.\n\n## Why a Digital Garden?\n\nUnlike traditional blogs that are often published, then forgotten, a digital garden is meant to grow and evolve over time. I'll be revisiting and updating content as my thoughts and understanding develop.\n\n## Topics I'll Cover\n\n- Technology projects I'm working on\n- Learning notes and discoveries\n- Workflow and productivity systems\n- Occasional personal reflections\n\n## Stay Connected\n\nFeel free to check back regularly to see what's growing in this garden. The journal section will be updated most frequently, while blog posts will appear when ideas have had time to mature.","src/content/blog/posts/starting-my-digital-garden.md","08c8e8ccdd410916",{"html":1570,"metadata":1571},"\u003Ch1 id=\"starting-my-digital-garden\">Starting My Digital Garden\u003C/h1>\n\u003Ch2 id=\"introduction\">Introduction\u003C/h2>\n\u003Cp>Today I’m launching my public digital garden - a space where I’ll share my thoughts, ideas, and projects with the world.\u003C/p>\n\u003Ch2 id=\"what-to-expect\">What to Expect\u003C/h2>\n\u003Cp>This site contains two main sections:\u003C/p>\n\u003Col>\n\u003Cli>\u003Cstrong>Journal\u003C/strong> - Daily notes and thoughts, more raw and in-the-moment\u003C/li>\n\u003Cli>\u003Cstrong>Blog\u003C/strong> - More structured and polished articles on various topics\u003C/li>\n\u003C/ol>\n\u003Cp>I’ll be using my daily journal to capture ideas as they happen, and some of these will evolve into more detailed blog posts over time.\u003C/p>\n\u003Ch2 id=\"why-a-digital-garden\">Why a Digital Garden?\u003C/h2>\n\u003Cp>Unlike traditional blogs that are often published, then forgotten, a digital garden is meant to grow and evolve over time. I’ll be revisiting and updating content as my thoughts and understanding develop.\u003C/p>\n\u003Ch2 id=\"topics-ill-cover\">Topics I’ll Cover\u003C/h2>\n\u003Cul>\n\u003Cli>Technology projects I’m working on\u003C/li>\n\u003Cli>Learning notes and discoveries\u003C/li>\n\u003Cli>Workflow and productivity systems\u003C/li>\n\u003Cli>Occasional personal reflections\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"stay-connected\">Stay Connected\u003C/h2>\n\u003Cp>Feel free to check back regularly to see what’s growing in this garden. The journal section will be updated most frequently, while blog posts will appear when ideas have had time to mature.\u003C/p>",{"headings":1572,"localImagePaths":1585,"remoteImagePaths":1586,"frontmatter":1587,"imagePaths":1590},[1573,1574,1575,1578,1579,1582],{"depth":52,"slug":439,"text":442},{"depth":55,"slug":899,"text":1209},{"depth":55,"slug":1576,"text":1577},"what-to-expect","What to Expect",{"depth":55,"slug":463,"text":464},{"depth":55,"slug":1580,"text":1581},"topics-ill-cover","Topics I’ll Cover",{"depth":55,"slug":1583,"text":1584},"stay-connected","Stay Connected",[],[],{"title":442,"pubDate":1588,"tags":1589,"draft":182,"heroImage":17},["Date","2025-04-19T00:00:00.000Z"],[9,1565,448],[],"posts/starting-my-digital-garden.md","posts/test-post",{"id":1592,"data":1594,"body":485,"filePath":1597,"digest":487,"rendered":1598,"legacyId":1608},{"title":480,"description":481,"pubDate":1595,"heroImage":17,"category":483,"tags":1596,"draft":43},["Date","2024-03-20T00:00:00.000Z"],[11],"src/content/blog/posts/test-post.md",{"html":489,"metadata":1599},{"headings":1600,"localImagePaths":1602,"remoteImagePaths":1603,"frontmatter":1604,"imagePaths":1607},[1601],{"depth":52,"slug":477,"text":480},[],[],{"title":480,"pubDate":1605,"description":481,"category":483,"tags":1606,"draft":43,"heroImage":17},["Date","2024-03-20T00:00:00.000Z"],[11],[],"posts/test-post.md","projects/argobox",{"id":1609,"data":1611,"body":1622,"filePath":1623,"digest":1624,"rendered":1625,"legacyId":1647},{"title":1612,"description":1613,"pubDate":1614,"heroImage":1615,"category":1046,"draft":182,"author":1198,"github":1616,"technologies":1617},"ArgoBox","A homelab server setup with Docker, Kubernetes, and various self-hosted services",["Date","2023-10-15T00:00:00.000Z"],"/images/argobox-hero.jpg","https://github.com/KeyArgo/homelab-infrastructure",[1618,178,1619,1620,1621],"Docker","Self-hosted","Proxmox","K3s","# ArgoBox\n\nArgoBox is a comprehensive homelab infrastructure project that combines virtualization, containerization, and automation to create a robust home server environment.\n\n## Overview\n\nThis project serves as the foundation for all my self-hosted services, including:\n\n- K3s Kubernetes cluster\n- GitOps with Flux CD\n- Monitoring with Prometheus and Grafana\n- Home automation tools\n- Media services\n- Development environment\n\n## Technical Stack\n\n- **Hypervisor**: Proxmox VE\n- **Container Orchestration**: K3s Kubernetes\n- **Configuration Management**: Ansible\n- **GitOps**: Flux CD\n- **Storage**: Longhorn, NFS\n- **Networking**: MetalLB, Cloudflare Tunnels\n- **Monitoring**: Prometheus, Grafana, Loki\n\n## Project Goals\n\n- Create a reliable, self-healing infrastructure\n- Implement GitOps practices for declarative configuration\n- Enable easy deployment of new services\n- Provide comprehensive monitoring and alerting\n- Document the setup for reproducibility\n\n## Current Status\n\nThe project is continuously evolving with new services and improvements being added regularly. Check the GitHub repository for the latest updates and documentation.","src/content/blog/projects/argobox.md","0ed2b0632f399d4b",{"html":1626,"metadata":1627},"\u003Ch1 id=\"argobox\">ArgoBox\u003C/h1>\n\u003Cp>ArgoBox is a comprehensive homelab infrastructure project that combines virtualization, containerization, and automation to create a robust home server environment.\u003C/p>\n\u003Ch2 id=\"overview\">Overview\u003C/h2>\n\u003Cp>This project serves as the foundation for all my self-hosted services, including:\u003C/p>\n\u003Cul>\n\u003Cli>K3s Kubernetes cluster\u003C/li>\n\u003Cli>GitOps with Flux CD\u003C/li>\n\u003Cli>Monitoring with Prometheus and Grafana\u003C/li>\n\u003Cli>Home automation tools\u003C/li>\n\u003Cli>Media services\u003C/li>\n\u003Cli>Development environment\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"technical-stack\">Technical Stack\u003C/h2>\n\u003Cul>\n\u003Cli>\u003Cstrong>Hypervisor\u003C/strong>: Proxmox VE\u003C/li>\n\u003Cli>\u003Cstrong>Container Orchestration\u003C/strong>: K3s Kubernetes\u003C/li>\n\u003Cli>\u003Cstrong>Configuration Management\u003C/strong>: Ansible\u003C/li>\n\u003Cli>\u003Cstrong>GitOps\u003C/strong>: Flux CD\u003C/li>\n\u003Cli>\u003Cstrong>Storage\u003C/strong>: Longhorn, NFS\u003C/li>\n\u003Cli>\u003Cstrong>Networking\u003C/strong>: MetalLB, Cloudflare Tunnels\u003C/li>\n\u003Cli>\u003Cstrong>Monitoring\u003C/strong>: Prometheus, Grafana, Loki\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"project-goals\">Project Goals\u003C/h2>\n\u003Cul>\n\u003Cli>Create a reliable, self-healing infrastructure\u003C/li>\n\u003Cli>Implement GitOps practices for declarative configuration\u003C/li>\n\u003Cli>Enable easy deployment of new services\u003C/li>\n\u003Cli>Provide comprehensive monitoring and alerting\u003C/li>\n\u003Cli>Document the setup for reproducibility\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"current-status\">Current Status\u003C/h2>\n\u003Cp>The project is continuously evolving with new services and improvements being added regularly. Check the GitHub repository for the latest updates and documentation.\u003C/p>",{"headings":1628,"localImagePaths":1641,"remoteImagePaths":1642,"frontmatter":1643,"imagePaths":1646},[1629,1631,1632,1635,1638],{"depth":52,"slug":1630,"text":1612},"argobox",{"depth":55,"slug":1344,"text":1345},{"depth":55,"slug":1633,"text":1634},"technical-stack","Technical Stack",{"depth":55,"slug":1636,"text":1637},"project-goals","Project Goals",{"depth":55,"slug":1639,"text":1640},"current-status","Current Status",[],[],{"title":1612,"pubDate":1644,"description":1613,"author":1198,"heroImage":1615,"category":1046,"technologies":1645,"github":1616,"draft":182},["Date","2023-10-15T00:00:00.000Z"],[1618,178,1619,1620,1621],[],"projects/argobox.md","posts/configs/k3s-cluster-config",{"id":1648,"data":1650,"body":1657,"filePath":1658,"digest":1659,"rendered":1660,"legacyId":1747},{"title":1651,"description":1652,"pubDate":1653,"heroImage":1654,"category":1046,"tags":1655,"draft":43,"author":1198},"K3s Cluster Configuration Guide","A comprehensive guide to configuring a K3s cluster for optimal performance and security in your homelab environment",["Date","2023-11-15T00:00:00.000Z"],"/images/k3s-config-hero.jpg",[180,181,73,1656,22,21],"configuration","\u003Cdiv class=\"draft-indicator\">\n \u003Csvg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n \u003Cpath d=\"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\">\u003C/path>\n \u003Cpath d=\"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z\">\u003C/path>\n \u003C/svg>\n \u003Cspan>Draft Article\u003C/span>\n\u003C/div>\n\n# K3s Cluster Configuration Guide\n\nAfter setting up your K3s cluster as described in our [K3s Installation Guide](/posts/k3s-installation-guide), it's time to configure it for optimal performance, security, and ease of management.\n\n## Table of Contents\n\n- [Introduction](#introduction)\n- [Basic Configuration](#basic-configuration)\n- [Networking Configuration](#networking-configuration)\n- [Storage Configuration](#storage-configuration)\n- [Security Hardening](#security-hardening)\n- [Resource Management](#resource-management)\n- [High Availability Setup](#high-availability-setup)\n- [Monitoring and Logging](#monitoring-and-logging)\n- [Troubleshooting](#troubleshooting)\n- [Conclusion](#conclusion)\n\n## Introduction\n\nThis guide covers the essential configuration aspects of a K3s cluster, providing you with the knowledge to create a robust and secure Kubernetes environment suitable for homelabs and small production deployments.\n\n## Basic Configuration\n\n### Config File Structure\n\nK3s uses a YAML configuration file that can be placed at `/etc/rancher/k3s/config.yaml`. Here's a basic example of what it might contain:\n\n```yaml\n# Server configuration\ntoken: \"your-secure-token\"\ntls-san:\n - \"k3s.example.com\"\n - \"192.168.1.100\"\nnode-label:\n - \"environment=production\"\n - \"location=home\"\n```\n\n### Environment Variables\n\nYou can also configure K3s using environment variables. These variables will override settings in the config file:\n\n```bash\n# Example environment variables for K3s configuration\nexport K3S_TOKEN=\"your-secure-token\"\nexport K3S_KUBECONFIG_MODE=\"644\"\nexport K3S_NODE_NAME=\"k3s-master\"\n```\n\n## Networking Configuration\n\n### CNI Configuration\n\nK3s comes with Flannel as the default CNI (Container Network Interface), but you can configure or replace it:\n\n```yaml\n# To disable the default flannel CNI\nflannel-backend: \"none\"\n\n# To use a different flannel backend\nflannel-backend: \"wireguard\"\n```\n\n### Load Balancer Configuration\n\nK3s includes ServiceLB (formerly known as Klipper) as a built-in load balancer:\n\n```yaml\n# To disable the default ServiceLB\ndisable-servicelb: true\n```\n\n## Storage Configuration\n\n### Local Path Provisioner\n\nK3s includes a local path provisioner by default, which you can configure or disable:\n\n```yaml\n# Disable the default local path provisioner\ndisable-local-storage: true\n```\n\n### Integration with External Storage\n\nGuidelines for configuring K3s to use NFS, Longhorn, or other storage solutions will be detailed here.\n\n## Security Hardening\n\n### Enabling Pod Security Policies\n\nSteps for implementing and configuring Pod Security Policies to enhance your cluster's security posture.\n\n### Network Policies\n\nExample configurations for implementing network policies that restrict pod-to-pod communication.\n\n## Resource Management\n\n### Setting Resource Limits\n\nHow to configure resource quotas and limits for namespaces and pods.\n\n### Autoscaling Configuration\n\nConfiguration options for horizontal and vertical pod autoscaling.\n\n## High Availability Setup\n\n### Multi-Server Configuration\n\nSteps to set up a highly available K3s cluster with multiple server nodes.\n\n### Embedded Database Configuration\n\nOptions for configuring the embedded etcd database for HA setups.\n\n## Monitoring and Logging\n\n### Metrics Server Configuration\n\nHow to enable and configure the metrics server for resource monitoring.\n\n### Log Collection\n\nOptions for configuring cluster-wide logging solutions.\n\n## Troubleshooting\n\n### Common Configuration Issues\n\nTypical misconfigurations and their solutions.\n\n### Debugging Techniques\n\nAdvanced techniques for troubleshooting configuration-related problems.\n\n## Conclusion\n\nA properly configured K3s cluster provides a solid foundation for running containerized applications in your homelab environment. By following this guide, you've learned how to optimize your cluster for performance, security, and reliability.\n\n\u003Cstyle>\n.draft-indicator {\n display: flex;\n align-items: center;\n gap: 8px;\n background-color: #f8f9fa;\n border-left: 4px solid #6c757d;\n padding: 12px 16px;\n margin-bottom: 24px;\n border-radius: 4px;\n color: #495057;\n}\n\n.draft-indicator svg {\n color: #6c757d;\n}\n\n.draft-indicator span {\n font-weight: 600;\n font-size: 16px;\n}\n\u003C/style>","src/content/blog/posts/configs/k3s-cluster-config.md","08441c59d44b9799",{"html":1661,"metadata":1662},"\u003Cdiv class=\"draft-indicator\">\n \u003Csvg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n \u003Cpath d=\"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\">\u003C/path>\n \u003Cpath d=\"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z\">\u003C/path>\n \u003C/svg>\n \u003Cspan>Draft Article\u003C/span>\n\u003C/div>\n\u003Ch1 id=\"k3s-cluster-configuration-guide\">K3s Cluster Configuration Guide\u003C/h1>\n\u003Cp>After setting up your K3s cluster as described in our \u003Ca href=\"/posts/k3s-installation-guide\">K3s Installation Guide\u003C/a>, it’s time to configure it for optimal performance, security, and ease of management.\u003C/p>\n\u003Ch2 id=\"table-of-contents\">Table of Contents\u003C/h2>\n\u003Cul>\n\u003Cli>\u003Ca href=\"#introduction\">Introduction\u003C/a>\u003C/li>\n\u003Cli>\u003Ca href=\"#basic-configuration\">Basic Configuration\u003C/a>\u003C/li>\n\u003Cli>\u003Ca href=\"#networking-configuration\">Networking Configuration\u003C/a>\u003C/li>\n\u003Cli>\u003Ca href=\"#storage-configuration\">Storage Configuration\u003C/a>\u003C/li>\n\u003Cli>\u003Ca href=\"#security-hardening\">Security Hardening\u003C/a>\u003C/li>\n\u003Cli>\u003Ca href=\"#resource-management\">Resource Management\u003C/a>\u003C/li>\n\u003Cli>\u003Ca href=\"#high-availability-setup\">High Availability Setup\u003C/a>\u003C/li>\n\u003Cli>\u003Ca href=\"#monitoring-and-logging\">Monitoring and Logging\u003C/a>\u003C/li>\n\u003Cli>\u003Ca href=\"#troubleshooting\">Troubleshooting\u003C/a>\u003C/li>\n\u003Cli>\u003Ca href=\"#conclusion\">Conclusion\u003C/a>\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"introduction\">Introduction\u003C/h2>\n\u003Cp>This guide covers the essential configuration aspects of a K3s cluster, providing you with the knowledge to create a robust and secure Kubernetes environment suitable for homelabs and small production deployments.\u003C/p>\n\u003Ch2 id=\"basic-configuration\">Basic Configuration\u003C/h2>\n\u003Ch3 id=\"config-file-structure\">Config File Structure\u003C/h3>\n\u003Cp>K3s uses a YAML configuration file that can be placed at \u003Ccode>/etc/rancher/k3s/config.yaml\u003C/code>. Here’s a basic example of what it might contain:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Server configuration\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">token\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">your-secure-token\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">tls-san\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">k3s.example.com\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">192.168.1.100\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">node-label\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">environment=production\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">location=home\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"environment-variables\">Environment Variables\u003C/h3>\n\u003Cp>You can also configure K3s using environment variables. These variables will override settings in the config file:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Example environment variables for K3s configuration\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\">export\u003C/span>\u003Cspan style=\"color:#BD93F9\"> K3S_TOKEN\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">your-secure-token\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\">export\u003C/span>\u003Cspan style=\"color:#BD93F9\"> K3S_KUBECONFIG_MODE\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">644\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\">export\u003C/span>\u003Cspan style=\"color:#BD93F9\"> K3S_NODE_NAME\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">k3s-master\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"networking-configuration\">Networking Configuration\u003C/h2>\n\u003Ch3 id=\"cni-configuration\">CNI Configuration\u003C/h3>\n\u003Cp>K3s comes with Flannel as the default CNI (Container Network Interface), but you can configure or replace it:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># To disable the default flannel CNI\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">flannel-backend\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">none\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># To use a different flannel backend\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">flannel-backend\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">wireguard\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"load-balancer-configuration\">Load Balancer Configuration\u003C/h3>\n\u003Cp>K3s includes ServiceLB (formerly known as Klipper) as a built-in load balancer:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># To disable the default ServiceLB\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">disable-servicelb\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> true\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"storage-configuration\">Storage Configuration\u003C/h2>\n\u003Ch3 id=\"local-path-provisioner\">Local Path Provisioner\u003C/h3>\n\u003Cp>K3s includes a local path provisioner by default, which you can configure or disable:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Disable the default local path provisioner\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">disable-local-storage\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> true\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"integration-with-external-storage\">Integration with External Storage\u003C/h3>\n\u003Cp>Guidelines for configuring K3s to use NFS, Longhorn, or other storage solutions will be detailed here.\u003C/p>\n\u003Ch2 id=\"security-hardening\">Security Hardening\u003C/h2>\n\u003Ch3 id=\"enabling-pod-security-policies\">Enabling Pod Security Policies\u003C/h3>\n\u003Cp>Steps for implementing and configuring Pod Security Policies to enhance your cluster’s security posture.\u003C/p>\n\u003Ch3 id=\"network-policies\">Network Policies\u003C/h3>\n\u003Cp>Example configurations for implementing network policies that restrict pod-to-pod communication.\u003C/p>\n\u003Ch2 id=\"resource-management\">Resource Management\u003C/h2>\n\u003Ch3 id=\"setting-resource-limits\">Setting Resource Limits\u003C/h3>\n\u003Cp>How to configure resource quotas and limits for namespaces and pods.\u003C/p>\n\u003Ch3 id=\"autoscaling-configuration\">Autoscaling Configuration\u003C/h3>\n\u003Cp>Configuration options for horizontal and vertical pod autoscaling.\u003C/p>\n\u003Ch2 id=\"high-availability-setup\">High Availability Setup\u003C/h2>\n\u003Ch3 id=\"multi-server-configuration\">Multi-Server Configuration\u003C/h3>\n\u003Cp>Steps to set up a highly available K3s cluster with multiple server nodes.\u003C/p>\n\u003Ch3 id=\"embedded-database-configuration\">Embedded Database Configuration\u003C/h3>\n\u003Cp>Options for configuring the embedded etcd database for HA setups.\u003C/p>\n\u003Ch2 id=\"monitoring-and-logging\">Monitoring and Logging\u003C/h2>\n\u003Ch3 id=\"metrics-server-configuration\">Metrics Server Configuration\u003C/h3>\n\u003Cp>How to enable and configure the metrics server for resource monitoring.\u003C/p>\n\u003Ch3 id=\"log-collection\">Log Collection\u003C/h3>\n\u003Cp>Options for configuring cluster-wide logging solutions.\u003C/p>\n\u003Ch2 id=\"troubleshooting\">Troubleshooting\u003C/h2>\n\u003Ch3 id=\"common-configuration-issues\">Common Configuration Issues\u003C/h3>\n\u003Cp>Typical misconfigurations and their solutions.\u003C/p>\n\u003Ch3 id=\"debugging-techniques\">Debugging Techniques\u003C/h3>\n\u003Cp>Advanced techniques for troubleshooting configuration-related problems.\u003C/p>\n\u003Ch2 id=\"conclusion\">Conclusion\u003C/h2>\n\u003Cp>A properly configured K3s cluster provides a solid foundation for running containerized applications in your homelab environment. By following this guide, you’ve learned how to optimize your cluster for performance, security, and reliability.\u003C/p>\n\u003Cstyle>\n.draft-indicator {\n display: flex;\n align-items: center;\n gap: 8px;\n background-color: #f8f9fa;\n border-left: 4px solid #6c757d;\n padding: 12px 16px;\n margin-bottom: 24px;\n border-radius: 4px;\n color: #495057;\n}\n\n.draft-indicator svg {\n color: #6c757d;\n}\n\n.draft-indicator span {\n font-weight: 600;\n font-size: 16px;\n}\n\u003C/style>",{"headings":1663,"localImagePaths":1741,"remoteImagePaths":1742,"frontmatter":1743,"imagePaths":1746},[1664,1666,1669,1670,1673,1676,1679,1682,1685,1688,1691,1694,1697,1700,1703,1706,1709,1712,1715,1718,1721,1724,1727,1730,1733,1734,1737,1740],{"depth":52,"slug":1665,"text":1651},"k3s-cluster-configuration-guide",{"depth":55,"slug":1667,"text":1668},"table-of-contents","Table of Contents",{"depth":55,"slug":899,"text":1209},{"depth":55,"slug":1671,"text":1672},"basic-configuration","Basic Configuration",{"depth":97,"slug":1674,"text":1675},"config-file-structure","Config File Structure",{"depth":97,"slug":1677,"text":1678},"environment-variables","Environment Variables",{"depth":55,"slug":1680,"text":1681},"networking-configuration","Networking Configuration",{"depth":97,"slug":1683,"text":1684},"cni-configuration","CNI Configuration",{"depth":97,"slug":1686,"text":1687},"load-balancer-configuration","Load Balancer Configuration",{"depth":55,"slug":1689,"text":1690},"storage-configuration","Storage Configuration",{"depth":97,"slug":1692,"text":1693},"local-path-provisioner","Local Path Provisioner",{"depth":97,"slug":1695,"text":1696},"integration-with-external-storage","Integration with External Storage",{"depth":55,"slug":1698,"text":1699},"security-hardening","Security Hardening",{"depth":97,"slug":1701,"text":1702},"enabling-pod-security-policies","Enabling Pod Security Policies",{"depth":97,"slug":1704,"text":1705},"network-policies","Network Policies",{"depth":55,"slug":1707,"text":1708},"resource-management","Resource Management",{"depth":97,"slug":1710,"text":1711},"setting-resource-limits","Setting Resource Limits",{"depth":97,"slug":1713,"text":1714},"autoscaling-configuration","Autoscaling Configuration",{"depth":55,"slug":1716,"text":1717},"high-availability-setup","High Availability Setup",{"depth":97,"slug":1719,"text":1720},"multi-server-configuration","Multi-Server Configuration",{"depth":97,"slug":1722,"text":1723},"embedded-database-configuration","Embedded Database Configuration",{"depth":55,"slug":1725,"text":1726},"monitoring-and-logging","Monitoring and Logging",{"depth":97,"slug":1728,"text":1729},"metrics-server-configuration","Metrics Server Configuration",{"depth":97,"slug":1731,"text":1732},"log-collection","Log Collection",{"depth":55,"slug":364,"text":365},{"depth":97,"slug":1735,"text":1736},"common-configuration-issues","Common Configuration Issues",{"depth":97,"slug":1738,"text":1739},"debugging-techniques","Debugging Techniques",{"depth":55,"slug":162,"text":163},[],[],{"title":1651,"pubDate":1744,"description":1652,"author":1198,"heroImage":1654,"category":1046,"tags":1745,"draft":43},["Date","2023-11-15T00:00:00.000Z"],[180,181,73,1656,22,21],[],"posts/configs/k3s-cluster-config.md","projects/placeholder",{"id":1748,"data":1750,"body":1757,"filePath":1758,"digest":1759,"rendered":1760,"legacyId":1771},{"title":1751,"description":1752,"pubDate":1753,"heroImage":445,"status":1754,"tech":1755},"Projects Collection","A placeholder document for the projects collection",["Date","2025-04-18T00:00:00.000Z"],"planning",[828,1756],"markdown","# Projects Collection\n\nThis is a placeholder file for the projects collection.","src/content/blog/projects/placeholder.md","0245feafbc5cc8a6",{"html":1761,"metadata":1762},"\u003Ch1 id=\"projects-collection\">Projects Collection\u003C/h1>\n\u003Cp>This is a placeholder file for the projects collection.\u003C/p>",{"headings":1763,"localImagePaths":1766,"remoteImagePaths":1767,"frontmatter":1768,"imagePaths":1770},[1764],{"depth":52,"slug":1765,"text":1751},"projects-collection",[],[],{"title":1751,"description":1752,"heroImage":445,"pubDate":1769,"status":1754,"tech":1755},["Date","2025-04-18T00:00:00.000Z"],[],"projects/placeholder.md","posts/rancher-kubernetes-management",{"id":1772,"data":1774,"body":1778,"filePath":1779,"digest":1780,"rendered":1781,"legacyId":1809},{"title":630,"description":631,"pubDate":1775,"updatedDate":1776,"heroImage":17,"category":507,"tags":1777},["Date","2025-04-19T00:00:00.000Z"],["Date","2025-04-18T00:00:00.000Z"],[635,180,181,266,636],"I've been running Kubernetes at home for years now, and I've tried just about every management tool out there. From kubectl and a bunch of YAML files to various dashboards and UIs, I've experimented with it all. But the one tool that's been a constant in my home lab journey is [Rancher](https://rancher.com/) - a complete container management platform that makes Kubernetes management almost... dare I say it... enjoyable?\n\nToday, I want to walk you through setting up Rancher in your home lab and show you some of the features that have made it indispensable for me.\n\n## What is Rancher and Why Should You Care?\n\nRancher is an open-source platform for managing Kubernetes clusters. Think of it as mission control for all your container workloads. It gives you:\n\n- A unified interface for managing multiple clusters (perfect if you're running different K8s distros)\n- Simplified deployment of applications via apps & marketplace\n- Built-in monitoring, logging, and alerting\n- User management and role-based access control\n- A clean, intuitive UI that's actually useful (rare in the Kubernetes world!)\n\nIf you're running even a single Kubernetes cluster at home, Rancher can save you countless hours of typing `kubectl` commands and editing YAML files by hand.\n\n## Setting Up Rancher in Your Home Lab\n\nThere are several ways to deploy Rancher, but I'll focus on two approaches that work well for home labs.\n\n### Option 1: Docker Deployment (Quickstart)\n\nThe fastest way to get up and running is with Docker:\n\n```bash\ndocker run -d --restart=unless-stopped \\\n -p 80:80 -p 443:443 \\\n --privileged \\\n rancher/rancher:latest\n```\n\nThat's it! Navigate to `https://your-server-ip` and you'll be prompted to set a password and server URL.\n\nBut while this method is quick, I prefer the next approach for a more production-like setup.\n\n### Option 2: Installing Rancher on K3s\n\nMy preferred method is to run Rancher on a lightweight Kubernetes distribution like K3s. This gives you better reliability and easier upgrades.\n\nFirst, install K3s:\n\n```bash\ncurl -sfL https://get.k3s.io | sh -\n```\n\nNext, install cert-manager (required for Rancher to manage certificates):\n\n```bash\nkubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.12.2/cert-manager.yaml\n```\n\nThen, install Rancher using Helm:\n\n```bash\nhelm repo add rancher-stable https://releases.rancher.com/server-charts/stable\nhelm repo update\n\nkubectl create namespace cattle-system\n\nhelm install rancher rancher-stable/rancher \\\n --namespace cattle-system \\\n --set hostname=rancher.yourdomain.com \\\n --set bootstrapPassword=admin\n```\n\nDepending on your home lab setup, you might want to use a load balancer or ingress controller. I use Traefik, which comes pre-installed with K3s:\n\n```yaml\napiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n name: rancher\n namespace: cattle-system\nspec:\n rules:\n - host: rancher.yourdomain.com\n http:\n paths:\n - path: /\n pathType: Prefix\n backend:\n service:\n name: rancher\n port:\n number: 80\n tls:\n - hosts:\n - rancher.yourdomain.com\n secretName: rancher-tls\n```\n\n## Importing Your Existing Clusters\n\nOnce Rancher is running, you can import your existing Kubernetes clusters. This is my favorite part because it doesn't require you to rebuild anything.\n\n1. In the Rancher UI, go to \"Cluster Management\"\n2. Click \"Import Existing\"\n3. Choose a name for your cluster\n4. Copy the provided kubectl command and run it on your existing cluster\n\nRancher will install its agent on your cluster and begin managing it. Magic!\n\n## Setting Up Monitoring\n\nRancher makes it dead simple to deploy Prometheus and Grafana for monitoring:\n\n1. From your cluster's dashboard, go to \"Apps\"\n2. Select \"Monitoring\" from the Charts\n3. Install with default settings (or customize as needed)\n\nIn minutes, you'll have a full monitoring stack with pre-configured dashboards for nodes, pods, workloads, and more.\n\nHere's what my Grafana dashboard looks like for my home K8s cluster:\n\n![Rancher Grafana Dashboard](/blog/images/posts//blog/images/services/rancher-monitoring.jpg)\n\n## Creating Deployments Through the UI\n\nWhile I'm a big fan of GitOps and declarative deployments, sometimes you just want to quickly spin up a container without writing YAML. Rancher makes this painless:\n\n1. Go to your cluster\n2. Select \"Workload > Deployments\"\n3. Click \"Create\"\n4. Fill in the form with your container details\n\nYou get a nice UI for setting environment variables, volumes, health checks, and more. Once you're happy with it, Rancher generates and applies the YAML behind the scenes.\n\n## Rancher Fleet for GitOps\n\nOne of the newer features I love is Fleet, Rancher's GitOps engine. It allows you to manage deployments across clusters using Git repositories:\n\n```yaml\n# Example fleet.yaml\ndefaultNamespace: monitoring\nhelm:\n releaseName: prometheus\n repo: https://prometheus-community.github.io/helm-charts\n chart: kube-prometheus-stack\n version: 39.4.0\n values:\n grafana:\n adminPassword: ${GRAFANA_PASSWORD}\ntargets:\n - name: prod\n clusterSelector:\n matchLabels:\n environment: production\n - name: dev\n clusterSelector:\n matchLabels:\n environment: development\n helm:\n values:\n resources:\n limits:\n memory: 1Gi\n requests:\n memory: 512Mi\n```\n\nWith Fleet, I maintain a Git repository with all my deployments, and Rancher automatically applies them to the appropriate clusters. When I push changes, they're automatically deployed - proper GitOps!\n\n## Rancher for Projects and Teams\n\nIf you're working with a team or want to compartmentalize your applications, Rancher's projects feature is fantastic:\n\n1. Create different projects within a cluster (e.g., \"Media,\" \"Home Automation,\" \"Development\")\n2. Assign namespaces to projects\n3. Set resource quotas for each project\n4. Create users and assign them to projects with specific permissions\n\nThis way, you can give friends or family members access to specific applications without worrying about them breaking your critical services.\n\n## Advanced: Custom Cluster Templates\n\nAs my home lab grew, I started using Rancher's cluster templates to ensure consistency across my Kubernetes installations:\n\n```yaml\napiVersion: management.cattle.io/v3\nkind: ClusterTemplate\nmetadata:\n name: homelab-standard\nspec:\n displayName: HomeStack Standard\n revisionName: homelab-standard-v1\n members:\n - accessType: owner\n userPrincipalName: user-abc123\n template:\n spec:\n rancherKubernetesEngineConfig:\n services:\n etcd:\n backupConfig:\n enabled: true\n intervalHours: 12\n retention: 6\n kubeApi:\n auditLog:\n enabled: true\n network:\n plugin: canal\n monitoring:\n provider: metrics-server\n addons: |-\n apiVersion: v1\n kind: Namespace\n metadata:\n name: cert-manager\n ---\n apiVersion: v1\n kind: Namespace\n metadata:\n name: ingress-nginx\n```\n\n## My Top Rancher Tips\n\nAfter years of using Rancher, here are my top tips:\n\n1. **Use the Rancher CLI**: For repetitive tasks, the CLI is faster than the UI:\n ```bash\n rancher login https://rancher.yourdomain.com --token token-abc123\n rancher kubectl get nodes\n ```\n\n2. **Set Up External Authentication**: Connect Rancher to your identity provider (I use GitHub):\n ```yaml\n # Sample GitHub auth config\n apiVersion: management.cattle.io/v3\n kind: AuthConfig\n metadata:\n name: github\n type: githubConfig\n properties:\n enabled: true\n clientId: your-github-client-id\n clientSecret: your-github-client-secret\n allowedPrincipals:\n - github_user://your-github-username\n - github_org://your-github-org\n ```\n\n3. **Create Node Templates**: If you're using RKE, save node templates for quick cluster expansion.\n\n4. **Use App Templates**: Save your common applications as templates for quick deployment.\n\n5. **Set Up Alerts**: Configure alerts for node health, pod failures, and resource constraints.\n\n## Dealing with Common Rancher Issues\n\nEven the best tools have their quirks. Here are some issues I've encountered and how I solved them:\n\n### Issue: Rancher UI Becomes Slow\n\nIf your Rancher UI starts lagging, check your browser's local storage. The Rancher UI caches a lot of data, which can build up over time:\n\n```javascript\n// Run this in your browser console while on the Rancher page\nlocalStorage.clear()\n```\n\n### Issue: Certificate Errors After DNS Changes\n\nIf you change your domain or DNS settings, Rancher certificates might need to be regenerated:\n\n```bash\nkubectl -n cattle-system delete secret tls-rancher-ingress\nkubectl -n cattle-system delete secret tls-ca\n```\n\nThen restart the Rancher pods:\n\n```bash\nkubectl -n cattle-system rollout restart deploy/rancher\n```\n\n### Issue: Stuck Cluster Imports\n\nIf a cluster gets stuck during import, clean up the agent resources and try again:\n\n```bash\nkubectl delete clusterrole cattle-admin cluster-owner\nkubectl delete clusterrolebinding cattle-admin-binding cluster-owner\nkubectl delete namespace cattle-system\n```\n\n## The Future of Rancher\n\nWith SUSE's acquisition of Rancher Labs, the future looks bright. The latest Rancher updates have added:\n\n- Better integration with cloud providers\n- Improved security features\n- Enhanced multi-cluster management\n- Lower resource requirements (great for home labs)\n\nMy wish list for future versions includes:\n\n- Native GitOps for everything (not just workloads)\n- Better templating for one-click deployments\n- More pre-configured monitoring dashboards\n\n## Wrapping Up\n\nRancher has transformed how I manage my home Kubernetes clusters. What used to be a complex, time-consuming task is now almost... fun? If you're running Kubernetes at home and haven't tried Rancher yet, you're missing out on one of the best tools in the Kubernetes ecosystem.\n\nSure, you could manage everything with kubectl and YAML files (and I still do that sometimes), but having a well-designed UI for management, monitoring, and troubleshooting saves countless hours and reduces the learning curve for those just getting started with Kubernetes.\n\nAre you using Rancher or another tool to manage your Kubernetes clusters? What's been your experience? Let me know in the comments!\n\n---\n\n_This post was last updated on March 5, 2024 with information about Rancher v2.7 features and Fleet GitOps capabilities._","src/content/blog/posts/rancher-kubernetes-management.md","b635b5fe4de870d3",{"html":1782,"metadata":1783},"\u003Cp>I’ve been running Kubernetes at home for years now, and I’ve tried just about every management tool out there. From kubectl and a bunch of YAML files to various dashboards and UIs, I’ve experimented with it all. But the one tool that’s been a constant in my home lab journey is \u003Ca href=\"https://rancher.com/\">Rancher\u003C/a> - a complete container management platform that makes Kubernetes management almost… dare I say it… enjoyable?\u003C/p>\n\u003Cp>Today, I want to walk you through setting up Rancher in your home lab and show you some of the features that have made it indispensable for me.\u003C/p>\n\u003Ch2 id=\"what-is-rancher-and-why-should-you-care\">What is Rancher and Why Should You Care?\u003C/h2>\n\u003Cp>Rancher is an open-source platform for managing Kubernetes clusters. Think of it as mission control for all your container workloads. It gives you:\u003C/p>\n\u003Cul>\n\u003Cli>A unified interface for managing multiple clusters (perfect if you’re running different K8s distros)\u003C/li>\n\u003Cli>Simplified deployment of applications via apps & marketplace\u003C/li>\n\u003Cli>Built-in monitoring, logging, and alerting\u003C/li>\n\u003Cli>User management and role-based access control\u003C/li>\n\u003Cli>A clean, intuitive UI that’s actually useful (rare in the Kubernetes world!)\u003C/li>\n\u003C/ul>\n\u003Cp>If you’re running even a single Kubernetes cluster at home, Rancher can save you countless hours of typing \u003Ccode>kubectl\u003C/code> commands and editing YAML files by hand.\u003C/p>\n\u003Ch2 id=\"setting-up-rancher-in-your-home-lab\">Setting Up Rancher in Your Home Lab\u003C/h2>\n\u003Cp>There are several ways to deploy Rancher, but I’ll focus on two approaches that work well for home labs.\u003C/p>\n\u003Ch3 id=\"option-1-docker-deployment-quickstart\">Option 1: Docker Deployment (Quickstart)\u003C/h3>\n\u003Cp>The fastest way to get up and running is with Docker:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">docker\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> run\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -d\u003C/span>\u003Cspan style=\"color:#BD93F9\"> --restart=unless-stopped\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> -p\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 80:80\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -p\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 443:443\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> --privileged\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> rancher/rancher:latest\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>That’s it! Navigate to \u003Ccode>https://your-server-ip\u003C/code> and you’ll be prompted to set a password and server URL.\u003C/p>\n\u003Cp>But while this method is quick, I prefer the next approach for a more production-like setup.\u003C/p>\n\u003Ch3 id=\"option-2-installing-rancher-on-k3s\">Option 2: Installing Rancher on K3s\u003C/h3>\n\u003Cp>My preferred method is to run Rancher on a lightweight Kubernetes distribution like K3s. This gives you better reliability and easier upgrades.\u003C/p>\n\u003Cp>First, install K3s:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">curl\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -sfL\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> https://get.k3s.io\u003C/span>\u003Cspan style=\"color:#FF79C6\"> |\u003C/span>\u003Cspan style=\"color:#50FA7B\"> sh\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> -\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Next, install cert-manager (required for Rancher to manage certificates):\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">kubectl\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> apply\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -f\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> https://github.com/jetstack/cert-manager/releases/download/v1.12.2/cert-manager.yaml\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Then, install Rancher using Helm:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">helm\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> repo\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> add\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> rancher-stable\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> https://releases.rancher.com/server-charts/stable\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">helm\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> repo\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> update\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">kubectl\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> create\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> namespace\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> cattle-system\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">helm\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> install\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> rancher\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> rancher-stable/rancher\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> --namespace\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> cattle-system\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> --set\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> hostname=rancher.yourdomain.com\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> --set\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> bootstrapPassword=admin\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Depending on your home lab setup, you might want to use a load balancer or ingress controller. I use Traefik, which comes pre-installed with K3s:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">apiVersion\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> networking.k8s.io/v1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">kind\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Ingress\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">metadata\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> rancher\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> namespace\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> cattle-system\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> rules\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> host\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> rancher.yourdomain.com\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> http\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> paths\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> path\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> pathType\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Prefix\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> backend\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> service\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> rancher\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> port\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> number\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 80\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> tls\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> hosts\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> rancher.yourdomain.com\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> secretName\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> rancher-tls\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"importing-your-existing-clusters\">Importing Your Existing Clusters\u003C/h2>\n\u003Cp>Once Rancher is running, you can import your existing Kubernetes clusters. This is my favorite part because it doesn’t require you to rebuild anything.\u003C/p>\n\u003Col>\n\u003Cli>In the Rancher UI, go to “Cluster Management”\u003C/li>\n\u003Cli>Click “Import Existing”\u003C/li>\n\u003Cli>Choose a name for your cluster\u003C/li>\n\u003Cli>Copy the provided kubectl command and run it on your existing cluster\u003C/li>\n\u003C/ol>\n\u003Cp>Rancher will install its agent on your cluster and begin managing it. Magic!\u003C/p>\n\u003Ch2 id=\"setting-up-monitoring\">Setting Up Monitoring\u003C/h2>\n\u003Cp>Rancher makes it dead simple to deploy Prometheus and Grafana for monitoring:\u003C/p>\n\u003Col>\n\u003Cli>From your cluster’s dashboard, go to “Apps”\u003C/li>\n\u003Cli>Select “Monitoring” from the Charts\u003C/li>\n\u003Cli>Install with default settings (or customize as needed)\u003C/li>\n\u003C/ol>\n\u003Cp>In minutes, you’ll have a full monitoring stack with pre-configured dashboards for nodes, pods, workloads, and more.\u003C/p>\n\u003Cp>Here’s what my Grafana dashboard looks like for my home K8s cluster:\u003C/p>\n\u003Cp>\u003Cimg src=\"/blog/images/posts//blog/images/services/rancher-monitoring.jpg\" alt=\"Rancher Grafana Dashboard\">\u003C/p>\n\u003Ch2 id=\"creating-deployments-through-the-ui\">Creating Deployments Through the UI\u003C/h2>\n\u003Cp>While I’m a big fan of GitOps and declarative deployments, sometimes you just want to quickly spin up a container without writing YAML. Rancher makes this painless:\u003C/p>\n\u003Col>\n\u003Cli>Go to your cluster\u003C/li>\n\u003Cli>Select “Workload > Deployments”\u003C/li>\n\u003Cli>Click “Create”\u003C/li>\n\u003Cli>Fill in the form with your container details\u003C/li>\n\u003C/ol>\n\u003Cp>You get a nice UI for setting environment variables, volumes, health checks, and more. Once you’re happy with it, Rancher generates and applies the YAML behind the scenes.\u003C/p>\n\u003Ch2 id=\"rancher-fleet-for-gitops\">Rancher Fleet for GitOps\u003C/h2>\n\u003Cp>One of the newer features I love is Fleet, Rancher’s GitOps engine. It allows you to manage deployments across clusters using Git repositories:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Example fleet.yaml\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">defaultNamespace\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> monitoring\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">helm\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> releaseName\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> prometheus\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> repo\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> https://prometheus-community.github.io/helm-charts\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> chart\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> kube-prometheus-stack\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> version\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 39.4.0\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> values\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> grafana\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> adminPassword\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ${GRAFANA_PASSWORD}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">targets\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> prod\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> clusterSelector\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> matchLabels\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> environment\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> production\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> dev\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> clusterSelector\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> matchLabels\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> environment\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> development\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> helm\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> values\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> resources\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> limits\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> memory\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 1Gi\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> requests\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> memory\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 512Mi\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>With Fleet, I maintain a Git repository with all my deployments, and Rancher automatically applies them to the appropriate clusters. When I push changes, they’re automatically deployed - proper GitOps!\u003C/p>\n\u003Ch2 id=\"rancher-for-projects-and-teams\">Rancher for Projects and Teams\u003C/h2>\n\u003Cp>If you’re working with a team or want to compartmentalize your applications, Rancher’s projects feature is fantastic:\u003C/p>\n\u003Col>\n\u003Cli>Create different projects within a cluster (e.g., “Media,” “Home Automation,” “Development”)\u003C/li>\n\u003Cli>Assign namespaces to projects\u003C/li>\n\u003Cli>Set resource quotas for each project\u003C/li>\n\u003Cli>Create users and assign them to projects with specific permissions\u003C/li>\n\u003C/ol>\n\u003Cp>This way, you can give friends or family members access to specific applications without worrying about them breaking your critical services.\u003C/p>\n\u003Ch2 id=\"advanced-custom-cluster-templates\">Advanced: Custom Cluster Templates\u003C/h2>\n\u003Cp>As my home lab grew, I started using Rancher’s cluster templates to ensure consistency across my Kubernetes installations:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">apiVersion\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> management.cattle.io/v3\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">kind\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ClusterTemplate\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">metadata\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> homelab-standard\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> displayName\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> HomeStack Standard\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> revisionName\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> homelab-standard-v1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> members\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> accessType\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> owner\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> userPrincipalName\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> user-abc123\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> template\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> rancherKubernetesEngineConfig\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> services\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> etcd\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> backupConfig\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> enabled\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> true\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> intervalHours\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 12\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> retention\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 6\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> kubeApi\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> auditLog\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> enabled\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> true\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> network\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> plugin\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> canal\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> monitoring\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> provider\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> metrics-server\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> addons\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#FF79C6\"> |-\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> apiVersion: v1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> kind: Namespace\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> metadata:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> name: cert-manager\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> ---\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> apiVersion: v1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> kind: Namespace\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> metadata:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> name: ingress-nginx\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"my-top-rancher-tips\">My Top Rancher Tips\u003C/h2>\n\u003Cp>After years of using Rancher, here are my top tips:\u003C/p>\n\u003Col>\n\u003Cli>\n\u003Cp>\u003Cstrong>Use the Rancher CLI\u003C/strong>: For repetitive tasks, the CLI is faster than the UI:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">rancher\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> login\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> https://rancher.yourdomain.com\u003C/span>\u003Cspan style=\"color:#BD93F9\"> --token\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> token-abc123\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">rancher\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> kubectl\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> get\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> nodes\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>Set Up External Authentication\u003C/strong>: Connect Rancher to your identity provider (I use GitHub):\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Sample GitHub auth config\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">apiVersion\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> management.cattle.io/v3\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">kind\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> AuthConfig\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">metadata\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> github\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">type\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> githubConfig\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">properties\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> enabled\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> true\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> clientId\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> your-github-client-id\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> clientSecret\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> your-github-client-secret\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> allowedPrincipals\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> github_user://your-github-username\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> github_org://your-github-org\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>Create Node Templates\u003C/strong>: If you’re using RKE, save node templates for quick cluster expansion.\u003C/p>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>Use App Templates\u003C/strong>: Save your common applications as templates for quick deployment.\u003C/p>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>Set Up Alerts\u003C/strong>: Configure alerts for node health, pod failures, and resource constraints.\u003C/p>\n\u003C/li>\n\u003C/ol>\n\u003Ch2 id=\"dealing-with-common-rancher-issues\">Dealing with Common Rancher Issues\u003C/h2>\n\u003Cp>Even the best tools have their quirks. Here are some issues I’ve encountered and how I solved them:\u003C/p>\n\u003Ch3 id=\"issue-rancher-ui-becomes-slow\">Issue: Rancher UI Becomes Slow\u003C/h3>\n\u003Cp>If your Rancher UI starts lagging, check your browser’s local storage. The Rancher UI caches a lot of data, which can build up over time:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"javascript\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\">// Run this in your browser console while on the Rancher page\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">localStorage.\u003C/span>\u003Cspan style=\"color:#50FA7B\">clear\u003C/span>\u003Cspan style=\"color:#F8F8F2\">()\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"issue-certificate-errors-after-dns-changes\">Issue: Certificate Errors After DNS Changes\u003C/h3>\n\u003Cp>If you change your domain or DNS settings, Rancher certificates might need to be regenerated:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">kubectl\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -n\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> cattle-system\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> delete\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> secret\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> tls-rancher-ingress\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">kubectl\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -n\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> cattle-system\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> delete\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> secret\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> tls-ca\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Then restart the Rancher pods:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">kubectl\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -n\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> cattle-system\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> rollout\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> restart\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> deploy/rancher\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"issue-stuck-cluster-imports\">Issue: Stuck Cluster Imports\u003C/h3>\n\u003Cp>If a cluster gets stuck during import, clean up the agent resources and try again:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">kubectl\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> delete\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> clusterrole\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> cattle-admin\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> cluster-owner\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">kubectl\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> delete\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> clusterrolebinding\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> cattle-admin-binding\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> cluster-owner\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">kubectl\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> delete\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> namespace\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> cattle-system\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"the-future-of-rancher\">The Future of Rancher\u003C/h2>\n\u003Cp>With SUSE’s acquisition of Rancher Labs, the future looks bright. The latest Rancher updates have added:\u003C/p>\n\u003Cul>\n\u003Cli>Better integration with cloud providers\u003C/li>\n\u003Cli>Improved security features\u003C/li>\n\u003Cli>Enhanced multi-cluster management\u003C/li>\n\u003Cli>Lower resource requirements (great for home labs)\u003C/li>\n\u003C/ul>\n\u003Cp>My wish list for future versions includes:\u003C/p>\n\u003Cul>\n\u003Cli>Native GitOps for everything (not just workloads)\u003C/li>\n\u003Cli>Better templating for one-click deployments\u003C/li>\n\u003Cli>More pre-configured monitoring dashboards\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"wrapping-up\">Wrapping Up\u003C/h2>\n\u003Cp>Rancher has transformed how I manage my home Kubernetes clusters. What used to be a complex, time-consuming task is now almost… fun? If you’re running Kubernetes at home and haven’t tried Rancher yet, you’re missing out on one of the best tools in the Kubernetes ecosystem.\u003C/p>\n\u003Cp>Sure, you could manage everything with kubectl and YAML files (and I still do that sometimes), but having a well-designed UI for management, monitoring, and troubleshooting saves countless hours and reduces the learning curve for those just getting started with Kubernetes.\u003C/p>\n\u003Cp>Are you using Rancher or another tool to manage your Kubernetes clusters? What’s been your experience? Let me know in the comments!\u003C/p>\n\u003Chr>\n\u003Cp>\u003Cem>This post was last updated on March 5, 2024 with information about Rancher v2.7 features and Fleet GitOps capabilities.\u003C/em>\u003C/p>",{"headings":1784,"localImagePaths":1802,"remoteImagePaths":1803,"frontmatter":1804,"imagePaths":1808},[1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,1795,1796,1797,1798,1799,1800,1801],{"depth":55,"slug":645,"text":646},{"depth":55,"slug":648,"text":649},{"depth":97,"slug":651,"text":652},{"depth":97,"slug":654,"text":655},{"depth":55,"slug":657,"text":658},{"depth":55,"slug":660,"text":661},{"depth":55,"slug":663,"text":664},{"depth":55,"slug":666,"text":667},{"depth":55,"slug":669,"text":670},{"depth":55,"slug":672,"text":673},{"depth":55,"slug":675,"text":676},{"depth":55,"slug":678,"text":679},{"depth":97,"slug":681,"text":682},{"depth":97,"slug":684,"text":685},{"depth":97,"slug":687,"text":688},{"depth":55,"slug":690,"text":691},{"depth":55,"slug":563,"text":564},[],[],{"title":630,"description":631,"pubDate":1805,"updatedDate":1806,"category":507,"tags":1807,"heroImage":17},["Date","2025-04-19T00:00:00.000Z"],["Date","2025-04-18T00:00:00.000Z"],[635,180,181,266,636],[],"posts/rancher-kubernetes-management.md","posts/vscode-server-remote-development",{"id":1810,"data":1812,"body":1816,"filePath":1817,"digest":1818,"rendered":1819,"legacyId":1857},{"title":704,"description":705,"pubDate":1813,"updatedDate":1814,"heroImage":17,"category":507,"tags":1815},["Date","2023-04-18T00:00:00.000Z"],["Date","2024-04-19T00:00:00.000Z"],[709,710,511,711,22],"If you're like me, you probably find yourself coding on multiple devices - maybe a desktop at home, a laptop when traveling, or even occasionally on a tablet. For years, keeping development environments in sync was a pain point. Enter [VS Code Server](https://code.visualstudio.com/docs/remote/vscode-server), the solution that has completely transformed my development workflow.\n\nToday, I want to show you how to set up your own self-hosted VS Code Server that lets you code from literally any device with a web browser, all while using your powerful home server for the heavy lifting.\n\n## Why VS Code Server?\n\nBefore we dive into the setup, let's talk about why you might want this:\n\n- **Consistent environment**: The same development setup, extensions, and configurations regardless of which device you're using.\n- **Resource optimization**: Run resource-intensive tasks (builds, tests) on your powerful server instead of your laptop.\n- **Work from anywhere**: Access your development environment from any device with a browser, even an iPad or a borrowed computer.\n- **Seamless switching**: Start working on one device and continue on another without missing a beat.\n\nI've been using this setup for months now, and it's been a game-changer for my productivity. Let's get into the setup!\n\n## Setting Up VS Code Server\n\nThere are a few ways to run VS Code Server. I'll cover the official method and my preferred Docker approach.\n\n### Option 1: Official CLI Installation\n\nThe VS Code team provides a CLI for setting up the server:\n\n```bash\n# Download and install the CLI\ncurl -fsSL https://code.visualstudio.com/sha/download?build=stable&os=cli-alpine-x64 -o vscode_cli.tar.gz\ntar -xf vscode_cli.tar.gz\nsudo mv code /usr/local/bin/\n\n# Start the server\ncode serve-web --accept-server-license-terms --host 0.0.0.0\n```\n\nThis method is straightforward but requires you to manage the process yourself.\n\n### Option 2: Docker Installation (My Preference)\n\nI prefer using Docker for easier updates and management. Here's my `docker-compose.yml`:\n\n```yaml\nversion: '3'\nservices:\n code-server:\n image: linuxserver/code-server:latest\n container_name: code-server\n environment:\n - PUID=1000\n - PGID=1000\n - TZ=America/Los_Angeles\n - PASSWORD=your_secure_password # Consider using Docker secrets instead\n - SUDO_PASSWORD=your_sudo_password # Optional\n - PROXY_DOMAIN=code.yourdomain.com # Optional\n volumes:\n - ./config:/config\n - /path/to/your/projects:/projects\n - /path/to/your/home:/home/coder\n ports:\n - 8443:8443\n restart: unless-stopped\n```\n\nRun it with:\n\n```bash\ndocker-compose up -d\n```\n\nYour VS Code Server will be available at `https://your-server-ip:8443`.\n\n### Option 3: Kubernetes Deployment\n\nFor those running Kubernetes (like me), here's a YAML manifest:\n\n```yaml\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: vscode-server\n namespace: development\nspec:\n replicas: 1\n selector:\n matchLabels:\n app: vscode-server\n template:\n metadata:\n labels:\n app: vscode-server\n spec:\n containers:\n - name: vscode-server\n image: linuxserver/code-server:latest\n env:\n - name: PUID\n value: \"1000\"\n - name: PGID\n value: \"1000\"\n - name: TZ\n value: \"America/Los_Angeles\"\n - name: PASSWORD\n valueFrom:\n secretKeyRef:\n name: vscode-secrets\n key: password\n ports:\n - containerPort: 8443\n volumeMounts:\n - name: config\n mountPath: /config\n - name: projects\n mountPath: /projects\n volumes:\n - name: config\n persistentVolumeClaim:\n claimName: vscode-config\n - name: projects\n persistentVolumeClaim:\n claimName: vscode-projects\n---\napiVersion: v1\nkind: Service\nmetadata:\n name: vscode-server\n namespace: development\nspec:\n selector:\n app: vscode-server\n ports:\n - port: 8443\n targetPort: 8443\n type: ClusterIP\n---\napiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n name: vscode-server\n namespace: development\n annotations:\n kubernetes.io/ingress.class: nginx\n cert-manager.io/cluster-issuer: letsencrypt-prod\nspec:\n tls:\n - hosts:\n - code.yourdomain.com\n secretName: vscode-tls\n rules:\n - host: code.yourdomain.com\n http:\n paths:\n - path: /\n pathType: Prefix\n backend:\n service:\n name: vscode-server\n port:\n number: 8443\n```\n\n## Accessing VS Code Server Securely\n\nYou don't want to expose your development environment directly to the internet without proper security. Here are my recommendations:\n\n### 1. Use a Reverse Proxy with SSL\n\nI use Traefik as a reverse proxy with automatic SSL certificate generation:\n\n```yaml\n# traefik.yml dynamic config\nhttp:\n routers:\n vscode:\n rule: \"Host(`code.yourdomain.com`)\"\n service: \"vscode\"\n entryPoints:\n - websecure\n tls:\n certResolver: letsencrypt\n services:\n vscode:\n loadBalancer:\n servers:\n - url: \"http://localhost:8443\"\n```\n\n### 2. Set Up Authentication\n\nThe LinuxServer image already includes basic authentication, but you can add another layer with something like Authelia:\n\n```yaml\n# authelia configuration.yml\naccess_control:\n default_policy: deny\n rules:\n - domain: code.yourdomain.com\n policy: two_factor\n subject: \"group:developers\"\n```\n\n### 3. Use Cloudflare Tunnel\n\nFor ultimate security, I use a Cloudflare Tunnel to avoid exposing any ports:\n\n```yaml\n# cloudflared config.yml\ntunnel: your-tunnel-id\ncredentials-file: /etc/cloudflared/creds.json\n\ningress:\n - hostname: code.yourdomain.com\n service: http://localhost:8443\n originRequest:\n noTLSVerify: true\n - service: http_status:404\n```\n\n## Configuring Your VS Code Server Environment\n\nOnce your server is running, it's time to set it up for optimal productivity:\n\n### 1. Install Essential Extensions\n\nHere are the must-have extensions I install first:\n\n```bash\n# From the VS Code terminal\ncode-server --install-extension ms-python.python\ncode-server --install-extension ms-azuretools.vscode-docker\ncode-server --install-extension dbaeumer.vscode-eslint\ncode-server --install-extension esbenp.prettier-vscode\ncode-server --install-extension github.copilot\ncode-server --install-extension golang.go\n```\n\nOr you can install them through the Extensions marketplace in the UI.\n\n### 2. Configure Settings Sync\n\nTo keep your settings in sync between instances:\n\n1. Open the Command Palette (Ctrl+Shift+P)\n2. Search for \"Settings Sync: Turn On\"\n3. Sign in with your GitHub or Microsoft account\n\n### 3. Set Up Git Authentication\n\nFor seamless Git operations:\n\n```bash\n# Generate a new SSH key if needed\nssh-keygen -t ed25519 -C \"your_email@example.com\"\n\n# Add to your GitHub/GitLab account\ncat ~/.ssh/id_ed25519.pub\n\n# Configure Git\ngit config --global user.name \"Your Name\"\ngit config --global user.email \"your_email@example.com\"\n```\n\n## Power User Features\n\nNow let's look at some advanced configurations that make VS Code Server even more powerful:\n\n### 1. Workspace Launcher\n\nI created a simple HTML page that lists all my projects for quick access:\n\n```html\n\u003C!DOCTYPE html>\n\u003Chtml>\n\u003Chead>\n \u003Ctitle>LaForceIT Workspace Launcher\u003C/title>\n \u003Cstyle>\n body {\n font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n background-color: #1e1e1e;\n color: #d4d4d4;\n max-width: 800px;\n margin: 0 auto;\n padding: 20px;\n }\n .project-list {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));\n gap: 15px;\n margin-top: 20px;\n }\n .project-card {\n background-color: #252526;\n border-radius: 5px;\n padding: 15px;\n transition: transform 0.2s;\n }\n .project-card:hover {\n transform: translateY(-5px);\n background-color: #2d2d2d;\n }\n a {\n color: #569cd6;\n text-decoration: none;\n }\n h1 { color: #569cd6; }\n h2 { color: #4ec9b0; }\n \u003C/style>\n\u003C/head>\n\u003Cbody>\n \u003Ch1>LaForceIT Workspace Launcher\u003C/h1>\n \u003Cdiv class=\"project-list\">\n \u003Cdiv class=\"project-card\">\n \u003Ch2>ArgoBox\u003C/h2>\n \u003Cp>My Kubernetes home lab platform\u003C/p>\n \u003Ca href=\"/projects/argobox\">Open Workspace\u003C/a>\n \u003C/div>\n \u003Cdiv class=\"project-card\">\n \u003Ch2>Blog\u003C/h2>\n \u003Cp>LaForceIT blog and digital garden\u003C/p>\n \u003Ca href=\"/projects/blog\">Open Workspace\u003C/a>\n \u003C/div>\n \u003C!-- Add more projects as needed -->\n \u003C/div>\n\u003C/body>\n\u003C/html>\n```\n\n### 2. Custom Terminal Profile\n\nAdd this to your `settings.json` for a better terminal experience:\n\n```json\n\"terminal.integrated.profiles.linux\": {\n \"bash\": {\n \"path\": \"bash\",\n \"icon\": \"terminal-bash\",\n \"args\": [\"-l\"]\n },\n \"zsh\": {\n \"path\": \"zsh\"\n },\n \"customProfile\": {\n \"path\": \"bash\",\n \"args\": [\"-c\", \"neofetch && bash -l\"],\n \"icon\": \"terminal-bash\",\n \"overrideName\": true\n }\n},\n\"terminal.integrated.defaultProfile.linux\": \"customProfile\"\n```\n\n### 3. Persistent Development Containers\n\nI use Docker-in-Docker to enable VS Code Dev Containers:\n\n```yaml\nversion: '3'\nservices:\n code-server:\n # ... other config from above\n volumes:\n # ... other volumes\n - /var/run/docker.sock:/var/run/docker.sock\n environment:\n # ... other env vars\n - DOCKER_HOST=unix:///var/run/docker.sock\n```\n\n## Real-World Examples: How I Use VS Code Server\n\nLet me share a few real-world examples of how I use this setup:\n\n### Example 1: Coding on iPad During Travel\n\nWhen traveling with just my iPad, I connect to my VS Code Server to work on my projects. With a Bluetooth keyboard and the amazing iPad screen, it's a surprisingly good experience. The heavy compilation happens on my server back home, so battery life on the iPad remains excellent.\n\n### Example 2: Pair Programming Sessions\n\nWhen helping friends debug issues, I can generate a temporary access link to my VS Code Server:\n\n```bash\n# Create a time-limited token\nTEMP_TOKEN=$(openssl rand -hex 16)\necho \"Token: $TEMP_TOKEN\" > /tmp/temp_token\ncurl -X POST -H \"Content-Type: application/json\" \\\n -d \"{\\\"token\\\":\\\"$TEMP_TOKEN\\\", \\\"expiresIn\\\":\\\"2h\\\"}\" \\\n http://localhost:8443/api/auth/temporary\n```\n\n### Example 3: Switching Between Devices\n\nI often start coding on my desktop, then switch to my laptop when moving to another room. With VS Code Server, I just close the browser on one device and open it on another - my entire session, including unsaved changes and terminal state, remains intact.\n\n## Monitoring and Maintaining Your VS Code Server\n\nTo keep your server running smoothly:\n\n### 1. Set Up Health Checks\n\nI use Uptime Kuma to monitor my VS Code Server:\n\n```yaml\n# Docker Compose snippet for Uptime Kuma\nuptime-kuma:\n image: louislam/uptime-kuma:latest\n container_name: uptime-kuma\n volumes:\n - ./uptime-kuma:/app/data\n ports:\n - 3001:3001\n restart: unless-stopped\n```\n\nAdd a monitor that checks `https://code.yourdomain.com/healthz` endpoint.\n\n### 2. Regular Backups\n\nSet up a cron job to back up your VS Code Server configuration:\n\n```bash\n# /etc/cron.daily/backup-vscode-server\n#!/bin/bash\ntar -czf /backups/vscode-server-$(date +%Y%m%d).tar.gz /path/to/config\n```\n\n### 3. Update Script\n\nCreate a script for easy updates:\n\n```bash\n#!/bin/bash\n# update-vscode-server.sh\ncd /path/to/docker-compose\ndocker-compose pull\ndocker-compose up -d\ndocker system prune -f\n```\n\n## Troubleshooting Common Issues\n\nHere are solutions to some issues I've encountered:\n\n### Issue: Extensions Not Installing\n\nIf extensions fail to install, try:\n\n```bash\n# Clear the extensio","src/content/blog/posts/vscode-server-remote-development.md","d3b1a198c5b7991a",{"html":1820,"metadata":1821},"\u003Cp>If you’re like me, you probably find yourself coding on multiple devices - maybe a desktop at home, a laptop when traveling, or even occasionally on a tablet. For years, keeping development environments in sync was a pain point. Enter \u003Ca href=\"https://code.visualstudio.com/docs/remote/vscode-server\">VS Code Server\u003C/a>, the solution that has completely transformed my development workflow.\u003C/p>\n\u003Cp>Today, I want to show you how to set up your own self-hosted VS Code Server that lets you code from literally any device with a web browser, all while using your powerful home server for the heavy lifting.\u003C/p>\n\u003Ch2 id=\"why-vs-code-server\">Why VS Code Server?\u003C/h2>\n\u003Cp>Before we dive into the setup, let’s talk about why you might want this:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Cstrong>Consistent environment\u003C/strong>: The same development setup, extensions, and configurations regardless of which device you’re using.\u003C/li>\n\u003Cli>\u003Cstrong>Resource optimization\u003C/strong>: Run resource-intensive tasks (builds, tests) on your powerful server instead of your laptop.\u003C/li>\n\u003Cli>\u003Cstrong>Work from anywhere\u003C/strong>: Access your development environment from any device with a browser, even an iPad or a borrowed computer.\u003C/li>\n\u003Cli>\u003Cstrong>Seamless switching\u003C/strong>: Start working on one device and continue on another without missing a beat.\u003C/li>\n\u003C/ul>\n\u003Cp>I’ve been using this setup for months now, and it’s been a game-changer for my productivity. Let’s get into the setup!\u003C/p>\n\u003Ch2 id=\"setting-up-vs-code-server\">Setting Up VS Code Server\u003C/h2>\n\u003Cp>There are a few ways to run VS Code Server. I’ll cover the official method and my preferred Docker approach.\u003C/p>\n\u003Ch3 id=\"option-1-official-cli-installation\">Option 1: Official CLI Installation\u003C/h3>\n\u003Cp>The VS Code team provides a CLI for setting up the server:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Download and install the CLI\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">curl\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -fsSL\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> https://code.visualstudio.com/sha/download?build=stable\u003C/span>\u003Cspan style=\"color:#F8F8F2\">&\u003C/span>\u003Cspan style=\"color:#BD93F9\">os\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#F1FA8C\">cli-alpine-x64\u003C/span>\u003Cspan style=\"color:#50FA7B\"> -o\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> vscode_cli.tar.gz\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">tar\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -xf\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> vscode_cli.tar.gz\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">sudo\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> mv\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> code\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /usr/local/bin/\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Start the server\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">code\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> serve-web\u003C/span>\u003Cspan style=\"color:#BD93F9\"> --accept-server-license-terms\u003C/span>\u003Cspan style=\"color:#BD93F9\"> --host\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 0.0.0.0\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>This method is straightforward but requires you to manage the process yourself.\u003C/p>\n\u003Ch3 id=\"option-2-docker-installation-my-preference\">Option 2: Docker Installation (My Preference)\u003C/h3>\n\u003Cp>I prefer using Docker for easier updates and management. Here’s my \u003Ccode>docker-compose.yml\u003C/code>:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">version\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> '\u003C/span>\u003Cspan style=\"color:#F1FA8C\">3\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">services\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> code-server\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> image\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> linuxserver/code-server:latest\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> container_name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> code-server\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> environment\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> PUID=1000\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> PGID=1000\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> TZ=America/Los_Angeles\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> PASSWORD=your_secure_password\u003C/span>\u003Cspan style=\"color:#6272A4\"> # Consider using Docker secrets instead\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> SUDO_PASSWORD=your_sudo_password\u003C/span>\u003Cspan style=\"color:#6272A4\"> # Optional\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> PROXY_DOMAIN=code.yourdomain.com\u003C/span>\u003Cspan style=\"color:#6272A4\"> # Optional\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> volumes\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ./config:/config\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /path/to/your/projects:/projects\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /path/to/your/home:/home/coder\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> ports\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 8443:8443\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> restart\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> unless-stopped\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Run it with:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">docker-compose\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> up\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -d\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Your VS Code Server will be available at \u003Ccode>https://your-server-ip:8443\u003C/code>.\u003C/p>\n\u003Ch3 id=\"option-3-kubernetes-deployment\">Option 3: Kubernetes Deployment\u003C/h3>\n\u003Cp>For those running Kubernetes (like me), here’s a YAML manifest:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">apiVersion\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> apps/v1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">kind\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Deployment\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">metadata\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> vscode-server\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> namespace\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> development\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> replicas\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> selector\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> matchLabels\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> app\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> vscode-server\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> template\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> metadata\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> labels\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> app\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> vscode-server\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> containers\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> vscode-server\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> image\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> linuxserver/code-server:latest\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> env\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> PUID\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> value\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">1000\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> PGID\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> value\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">1000\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> TZ\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> value\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">America/Los_Angeles\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> PASSWORD\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> valueFrom\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> secretKeyRef\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> vscode-secrets\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> key\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> password\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> ports\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> containerPort\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 8443\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> volumeMounts\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> config\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> mountPath\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /config\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> projects\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> mountPath\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /projects\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> volumes\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> config\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> persistentVolumeClaim\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> claimName\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> vscode-config\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> projects\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> persistentVolumeClaim\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> claimName\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> vscode-projects\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">---\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">apiVersion\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> v1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">kind\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Service\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">metadata\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> vscode-server\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> namespace\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> development\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> selector\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> app\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> vscode-server\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> ports\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> port\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 8443\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> targetPort\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 8443\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> type\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ClusterIP\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">---\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">apiVersion\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> networking.k8s.io/v1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">kind\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Ingress\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">metadata\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> vscode-server\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> namespace\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> development\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> annotations\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> kubernetes.io/ingress.class\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> nginx\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> cert-manager.io/cluster-issuer\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> letsencrypt-prod\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">spec\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> tls\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> hosts\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> code.yourdomain.com\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> secretName\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> vscode-tls\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> rules\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> host\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> code.yourdomain.com\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> http\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> paths\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> path\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> pathType\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Prefix\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> backend\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> service\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> vscode-server\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> port\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> number\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 8443\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"accessing-vs-code-server-securely\">Accessing VS Code Server Securely\u003C/h2>\n\u003Cp>You don’t want to expose your development environment directly to the internet without proper security. Here are my recommendations:\u003C/p>\n\u003Ch3 id=\"1-use-a-reverse-proxy-with-ssl\">1. Use a Reverse Proxy with SSL\u003C/h3>\n\u003Cp>I use Traefik as a reverse proxy with automatic SSL certificate generation:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># traefik.yml dynamic config\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">http\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> routers\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> vscode\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> rule\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Host(`code.yourdomain.com`)\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> service\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">vscode\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> entryPoints\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> websecure\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> tls\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> certResolver\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> letsencrypt\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> services\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> vscode\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> loadBalancer\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> servers\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> url\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">http://localhost:8443\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"2-set-up-authentication\">2. Set Up Authentication\u003C/h3>\n\u003Cp>The LinuxServer image already includes basic authentication, but you can add another layer with something like Authelia:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># authelia configuration.yml\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">access_control\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> default_policy\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> deny\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> rules\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> domain\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> code.yourdomain.com\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> policy\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> two_factor\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> subject\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">group:developers\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"3-use-cloudflare-tunnel\">3. Use Cloudflare Tunnel\u003C/h3>\n\u003Cp>For ultimate security, I use a Cloudflare Tunnel to avoid exposing any ports:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># cloudflared config.yml\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">tunnel\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> your-tunnel-id\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">credentials-file\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /etc/cloudflared/creds.json\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">ingress\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> hostname\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> code.yourdomain.com\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> service\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> http://localhost:8443\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> originRequest\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> noTLSVerify\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> true\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> service\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> http_status:404\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"configuring-your-vs-code-server-environment\">Configuring Your VS Code Server Environment\u003C/h2>\n\u003Cp>Once your server is running, it’s time to set it up for optimal productivity:\u003C/p>\n\u003Ch3 id=\"1-install-essential-extensions\">1. Install Essential Extensions\u003C/h3>\n\u003Cp>Here are the must-have extensions I install first:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># From the VS Code terminal\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">code-server\u003C/span>\u003Cspan style=\"color:#BD93F9\"> --install-extension\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ms-python.python\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">code-server\u003C/span>\u003Cspan style=\"color:#BD93F9\"> --install-extension\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ms-azuretools.vscode-docker\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">code-server\u003C/span>\u003Cspan style=\"color:#BD93F9\"> --install-extension\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> dbaeumer.vscode-eslint\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">code-server\u003C/span>\u003Cspan style=\"color:#BD93F9\"> --install-extension\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> esbenp.prettier-vscode\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">code-server\u003C/span>\u003Cspan style=\"color:#BD93F9\"> --install-extension\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> github.copilot\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">code-server\u003C/span>\u003Cspan style=\"color:#BD93F9\"> --install-extension\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> golang.go\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Or you can install them through the Extensions marketplace in the UI.\u003C/p>\n\u003Ch3 id=\"2-configure-settings-sync\">2. Configure Settings Sync\u003C/h3>\n\u003Cp>To keep your settings in sync between instances:\u003C/p>\n\u003Col>\n\u003Cli>Open the Command Palette (Ctrl+Shift+P)\u003C/li>\n\u003Cli>Search for “Settings Sync: Turn On”\u003C/li>\n\u003Cli>Sign in with your GitHub or Microsoft account\u003C/li>\n\u003C/ol>\n\u003Ch3 id=\"3-set-up-git-authentication\">3. Set Up Git Authentication\u003C/h3>\n\u003Cp>For seamless Git operations:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Generate a new SSH key if needed\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">ssh-keygen\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -t\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ed25519\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -C\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">your_email@example.com\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Add to your GitHub/GitLab account\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">cat\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ~/.ssh/id_ed25519.pub\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Configure Git\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">git\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> config\u003C/span>\u003Cspan style=\"color:#BD93F9\"> --global\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> user.name\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Your Name\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">git\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> config\u003C/span>\u003Cspan style=\"color:#BD93F9\"> --global\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> user.email\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">your_email@example.com\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"power-user-features\">Power User Features\u003C/h2>\n\u003Cp>Now let’s look at some advanced configurations that make VS Code Server even more powerful:\u003C/p>\n\u003Ch3 id=\"1-workspace-launcher\">1. Workspace Launcher\u003C/h3>\n\u003Cp>I created a simple HTML page that lists all my projects for quick access:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"html\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"><!\u003C/span>\u003Cspan style=\"color:#FF79C6\">DOCTYPE\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\"> html\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"><\u003C/span>\u003Cspan style=\"color:#FF79C6\">html\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"><\u003C/span>\u003Cspan style=\"color:#FF79C6\">head\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> <\u003C/span>\u003Cspan style=\"color:#FF79C6\">title\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>LaForceIT Workspace Launcher</\u003C/span>\u003Cspan style=\"color:#FF79C6\">title\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> <\u003C/span>\u003Cspan style=\"color:#FF79C6\">style\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> body\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> font-family\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> '\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Segoe UI\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#BD93F9\">Tahoma\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, Geneva, \u003C/span>\u003Cspan style=\"color:#BD93F9\">Verdana\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#BD93F9\">sans-serif\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> background-color\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> #1e1e1e\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> color\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> #d4d4d4\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> max-width\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 800\u003C/span>\u003Cspan style=\"color:#FF79C6\">px\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> margin\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 0\u003C/span>\u003Cspan style=\"color:#BD93F9\"> auto\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> padding\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 20\u003C/span>\u003Cspan style=\"color:#FF79C6\">px\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B;font-style:italic\"> .project-list\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> display\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> grid\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> grid-template-columns\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> repeat\u003C/span>\u003Cspan style=\"color:#F8F8F2\">(\u003C/span>\u003Cspan style=\"color:#BD93F9\">auto-fill\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#8BE9FD\">minmax\u003C/span>\u003Cspan style=\"color:#F8F8F2\">(\u003C/span>\u003Cspan style=\"color:#BD93F9\">200\u003C/span>\u003Cspan style=\"color:#FF79C6\">px\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#BD93F9\">1\u003C/span>\u003Cspan style=\"color:#FF79C6\">fr\u003C/span>\u003Cspan style=\"color:#F8F8F2\">));\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> gap\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 15\u003C/span>\u003Cspan style=\"color:#FF79C6\">px\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> margin-top\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 20\u003C/span>\u003Cspan style=\"color:#FF79C6\">px\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B;font-style:italic\"> .project-card\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> background-color\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> #252526\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> border-radius\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 5\u003C/span>\u003Cspan style=\"color:#FF79C6\">px\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> padding\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 15\u003C/span>\u003Cspan style=\"color:#FF79C6\">px\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> transition\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> transform \u003C/span>\u003Cspan style=\"color:#BD93F9\">0.2\u003C/span>\u003Cspan style=\"color:#FF79C6\">s\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B;font-style:italic\"> .project-card\u003C/span>\u003Cspan style=\"color:#FF79C6;font-style:italic\">:\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\">hover\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> transform\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> translateY\u003C/span>\u003Cspan style=\"color:#F8F8F2\">(\u003C/span>\u003Cspan style=\"color:#BD93F9\">-5\u003C/span>\u003Cspan style=\"color:#FF79C6\">px\u003C/span>\u003Cspan style=\"color:#F8F8F2\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> background-color\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> #2d2d2d\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> a\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> color\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> #569cd6\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> text-decoration\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> none\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> h1\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> { \u003C/span>\u003Cspan style=\"color:#8BE9FD\">color\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> #569cd6\u003C/span>\u003Cspan style=\"color:#F8F8F2\">; }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> h2\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> { \u003C/span>\u003Cspan style=\"color:#8BE9FD\">color\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> #4ec9b0\u003C/span>\u003Cspan style=\"color:#F8F8F2\">; }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> </\u003C/span>\u003Cspan style=\"color:#FF79C6\">style\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"></\u003C/span>\u003Cspan style=\"color:#FF79C6\">head\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"><\u003C/span>\u003Cspan style=\"color:#FF79C6\">body\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> <\u003C/span>\u003Cspan style=\"color:#FF79C6\">h1\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>LaForceIT Workspace Launcher</\u003C/span>\u003Cspan style=\"color:#FF79C6\">h1\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> <\u003C/span>\u003Cspan style=\"color:#FF79C6\">div\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\"> class\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">project-list\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> <\u003C/span>\u003Cspan style=\"color:#FF79C6\">div\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\"> class\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">project-card\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> <\u003C/span>\u003Cspan style=\"color:#FF79C6\">h2\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>ArgoBox</\u003C/span>\u003Cspan style=\"color:#FF79C6\">h2\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> <\u003C/span>\u003Cspan style=\"color:#FF79C6\">p\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>My Kubernetes home lab platform</\u003C/span>\u003Cspan style=\"color:#FF79C6\">p\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> <\u003C/span>\u003Cspan style=\"color:#FF79C6\">a\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\"> href\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">/projects/argobox\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>Open Workspace</\u003C/span>\u003Cspan style=\"color:#FF79C6\">a\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> </\u003C/span>\u003Cspan style=\"color:#FF79C6\">div\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> <\u003C/span>\u003Cspan style=\"color:#FF79C6\">div\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\"> class\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">project-card\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> <\u003C/span>\u003Cspan style=\"color:#FF79C6\">h2\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>Blog</\u003C/span>\u003Cspan style=\"color:#FF79C6\">h2\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> <\u003C/span>\u003Cspan style=\"color:#FF79C6\">p\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>LaForceIT blog and digital garden</\u003C/span>\u003Cspan style=\"color:#FF79C6\">p\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> <\u003C/span>\u003Cspan style=\"color:#FF79C6\">a\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\"> href\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">/projects/blog\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>Open Workspace</\u003C/span>\u003Cspan style=\"color:#FF79C6\">a\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> </\u003C/span>\u003Cspan style=\"color:#FF79C6\">div\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> <!-- Add more projects as needed -->\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> </\u003C/span>\u003Cspan style=\"color:#FF79C6\">div\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"></\u003C/span>\u003Cspan style=\"color:#FF79C6\">body\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"></\u003C/span>\u003Cspan style=\"color:#FF79C6\">html\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"2-custom-terminal-profile\">2. Custom Terminal Profile\u003C/h3>\n\u003Cp>Add this to your \u003Ccode>settings.json\u003C/code> for a better terminal experience:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"json\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">terminal.integrated.profiles.linux\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">: {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">bash\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">path\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">bash\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">icon\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">terminal-bash\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">args\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">-l\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">]\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">zsh\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">path\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">zsh\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">customProfile\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">path\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">bash\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">args\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">-c\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">neofetch && bash -l\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">],\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">icon\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">terminal-bash\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FE\"> \"\u003C/span>\u003Cspan style=\"color:#8BE9FD\">overrideName\u003C/span>\u003Cspan style=\"color:#8BE9FE\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> true\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">},\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">terminal.integrated.defaultProfile.linux\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">: \u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">customProfile\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"3-persistent-development-containers\">3. Persistent Development Containers\u003C/h3>\n\u003Cp>I use Docker-in-Docker to enable VS Code Dev Containers:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">version\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> '\u003C/span>\u003Cspan style=\"color:#F1FA8C\">3\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">services\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> code-server\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> # ... other config from above\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> volumes\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> # ... other volumes\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /var/run/docker.sock:/var/run/docker.sock\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> environment\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> # ... other env vars\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> DOCKER_HOST=unix:///var/run/docker.sock\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"real-world-examples-how-i-use-vs-code-server\">Real-World Examples: How I Use VS Code Server\u003C/h2>\n\u003Cp>Let me share a few real-world examples of how I use this setup:\u003C/p>\n\u003Ch3 id=\"example-1-coding-on-ipad-during-travel\">Example 1: Coding on iPad During Travel\u003C/h3>\n\u003Cp>When traveling with just my iPad, I connect to my VS Code Server to work on my projects. With a Bluetooth keyboard and the amazing iPad screen, it’s a surprisingly good experience. The heavy compilation happens on my server back home, so battery life on the iPad remains excellent.\u003C/p>\n\u003Ch3 id=\"example-2-pair-programming-sessions\">Example 2: Pair Programming Sessions\u003C/h3>\n\u003Cp>When helping friends debug issues, I can generate a temporary access link to my VS Code Server:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Create a time-limited token\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\">TEMP_TOKEN\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#F8F8F2\">$(\u003C/span>\u003Cspan style=\"color:#50FA7B\">openssl\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> rand\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -hex\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 16\u003C/span>\u003Cspan style=\"color:#F8F8F2\">)\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">echo\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Token: \u003C/span>\u003Cspan style=\"color:#BD93F9\">$TEMP_TOKEN\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\"> >\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /tmp/temp_token\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">curl\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -X\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> POST\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -H\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Content-Type: application/json\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> -d\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">{\u003C/span>\u003Cspan style=\"color:#FF79C6\">\\\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">token\u003C/span>\u003Cspan style=\"color:#FF79C6\">\\\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">:\u003C/span>\u003Cspan style=\"color:#FF79C6\">\\\"\u003C/span>\u003Cspan style=\"color:#BD93F9\">$TEMP_TOKEN\u003C/span>\u003Cspan style=\"color:#FF79C6\">\\\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">, \u003C/span>\u003Cspan style=\"color:#FF79C6\">\\\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">expiresIn\u003C/span>\u003Cspan style=\"color:#FF79C6\">\\\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">:\u003C/span>\u003Cspan style=\"color:#FF79C6\">\\\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">2h\u003C/span>\u003Cspan style=\"color:#FF79C6\">\\\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">}\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#FF79C6\"> \\\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F1FA8C\"> http://localhost:8443/api/auth/temporary\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"example-3-switching-between-devices\">Example 3: Switching Between Devices\u003C/h3>\n\u003Cp>I often start coding on my desktop, then switch to my laptop when moving to another room. With VS Code Server, I just close the browser on one device and open it on another - my entire session, including unsaved changes and terminal state, remains intact.\u003C/p>\n\u003Ch2 id=\"monitoring-and-maintaining-your-vs-code-server\">Monitoring and Maintaining Your VS Code Server\u003C/h2>\n\u003Cp>To keep your server running smoothly:\u003C/p>\n\u003Ch3 id=\"1-set-up-health-checks\">1. Set Up Health Checks\u003C/h3>\n\u003Cp>I use Uptime Kuma to monitor my VS Code Server:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Docker Compose snippet for Uptime Kuma\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">uptime-kuma\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> image\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> louislam/uptime-kuma:latest\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> container_name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> uptime-kuma\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> volumes\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ./uptime-kuma:/app/data\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> ports\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> 3001:3001\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> restart\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> unless-stopped\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Add a monitor that checks \u003Ccode>https://code.yourdomain.com/healthz\u003C/code> endpoint.\u003C/p>\n\u003Ch3 id=\"2-regular-backups\">2. Regular Backups\u003C/h3>\n\u003Cp>Set up a cron job to back up your VS Code Server configuration:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># /etc/cron.daily/backup-vscode-server\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\">#!/bin/bash\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">tar\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -czf\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /backups/vscode-server-\u003C/span>\u003Cspan style=\"color:#F8F8F2\">$(\u003C/span>\u003Cspan style=\"color:#50FA7B\">date\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> +%Y%m%d\u003C/span>\u003Cspan style=\"color:#F8F8F2\">)\u003C/span>\u003Cspan style=\"color:#F1FA8C\">.tar.gz\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /path/to/config\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"3-update-script\">3. Update Script\u003C/h3>\n\u003Cp>Create a script for easy updates:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\">#!/bin/bash\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># update-vscode-server.sh\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">cd\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /path/to/docker-compose\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">docker-compose\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> pull\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">docker-compose\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> up\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -d\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">docker\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> system\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> prune\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -f\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"troubleshooting-common-issues\">Troubleshooting Common Issues\u003C/h2>\n\u003Cp>Here are solutions to some issues I’ve encountered:\u003C/p>\n\u003Ch3 id=\"issue-extensions-not-installing\">Issue: Extensions Not Installing\u003C/h3>\n\u003Cp>If extensions fail to install, try:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Clear the extensio\u003C/span>\u003C/span>\u003C/code>\u003C/pre>",{"headings":1822,"localImagePaths":1850,"remoteImagePaths":1851,"frontmatter":1852,"imagePaths":1856},[1823,1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849],{"depth":55,"slug":720,"text":721},{"depth":55,"slug":723,"text":724},{"depth":97,"slug":726,"text":727},{"depth":97,"slug":729,"text":730},{"depth":97,"slug":732,"text":733},{"depth":55,"slug":735,"text":736},{"depth":97,"slug":738,"text":739},{"depth":97,"slug":741,"text":742},{"depth":97,"slug":744,"text":745},{"depth":55,"slug":747,"text":748},{"depth":97,"slug":750,"text":751},{"depth":97,"slug":753,"text":754},{"depth":97,"slug":756,"text":757},{"depth":55,"slug":759,"text":760},{"depth":97,"slug":762,"text":763},{"depth":97,"slug":765,"text":766},{"depth":97,"slug":768,"text":769},{"depth":55,"slug":771,"text":772},{"depth":97,"slug":774,"text":775},{"depth":97,"slug":777,"text":778},{"depth":97,"slug":780,"text":781},{"depth":55,"slug":783,"text":784},{"depth":97,"slug":786,"text":787},{"depth":97,"slug":789,"text":790},{"depth":97,"slug":792,"text":793},{"depth":55,"slug":795,"text":796},{"depth":97,"slug":798,"text":799},[],[],{"title":704,"description":705,"pubDate":1853,"updatedDate":1854,"category":507,"tags":1855,"heroImage":17},["Date","2023-04-18T00:00:00.000Z"],["Date","2024-04-19T00:00:00.000Z"],[709,710,511,711,22],[],"posts/vscode-server-remote-development.md","posts/quartz-digital-garden",{"id":1858,"data":1860,"body":1864,"filePath":1865,"digest":1866,"rendered":1867,"legacyId":1895},{"title":821,"description":822,"pubDate":1861,"updatedDate":1862,"heroImage":17,"category":507,"tags":1863},["Date","2025-04-18T00:00:00.000Z"],["Date","2025-04-19T00:00:00.000Z"],[826,827,448,449,828],"I've been taking digital notes for decades now. From simple `.txt` files to OneNote, Evernote, Notion, and now Obsidian. But for years, I've been wrestling with a question: how do I share my knowledge with others in a way that preserves the connections between ideas?\n\nEnter [Quartz](https://quartz.jzhao.xyz/) - an open-source static site generator designed specifically for transforming Obsidian vaults into interconnected digital gardens. I've been using it with Astro to power this very blog, and today I want to show you how you can do the same.\n\n## What is a Digital Garden?\n\nBefore we dive into the technical stuff, let's talk about what a digital garden actually is. Unlike traditional blogs organized chronologically, a digital garden is more like... well, a garden! It's a collection of interconnected notes that grow over time.\n\nThink of each note as a plant. Some are seedlings (early ideas), some are in full bloom (well-developed thoughts), and others might be somewhere in between. The beauty of a digital garden is that it evolves organically, with connections forming between ideas just as they do in our brains.\n\n## Why Quartz + Obsidian + Astro?\n\nI settled on this stack after trying numerous solutions, and here's why:\n\n- **Obsidian**: Provides a fantastic editing experience with bi-directional linking, graph views, and markdown support.\n- **Quartz**: Transforms Obsidian vaults into interconnected websites with minimal configuration.\n- **Astro**: Adds flexibility for custom layouts, components, and integrations not available in Quartz alone.\n\nIt's a match made in heaven - I get the best note-taking experience with Obsidian, the connection-preserving features of Quartz, and the full power of a modern web framework with Astro.\n\n## Setting Up Your Digital Garden\n\nLet's walk through how to set this up step by step.\n\n### Step 1: Install Obsidian and Create a Vault\n\nIf you haven't already, [download Obsidian](https://obsidian.md/) and create a new vault for your digital garden content. I recommend having a separate vault for public content to keep it clean.\n\n### Step 2: Set Up Quartz\n\nQuartz is essentially a template for your Obsidian content. Here's how to get it running:\n\n```bash\n# Clone the Quartz repository\ngit clone https://github.com/jackyzha0/quartz.git\ncd quartz\n\n# Install dependencies\nnpm install\n\n# Copy your Obsidian vault content to the content folder\n# (or symlink it, which is what I do)\nln -s /path/to/your/obsidian/vault content\n```\n\nOnce installed, you can customize your Quartz configuration in the `quartz.config.ts` file. Here's a snippet of mine:\n\n```typescript\n// quartz.config.ts\nconst config: QuartzConfig = {\n configuration: {\n pageTitle: \"LaForceIT Digital Garden\",\n enableSPA: true,\n enablePopovers: true,\n analytics: {\n provider: \"plausible\",\n },\n baseUrl: \"blog.laforceit.com\",\n ignorePatterns: [\"private\", \"templates\", \".obsidian\"],\n theme: {\n typography: {\n header: \"Space Grotesk\",\n body: \"Space Grotesk\",\n code: \"JetBrains Mono\",\n },\n colors: {\n lightMode: {\n light: \"#fafafa\",\n lightgray: \"#e5e5e5\",\n gray: \"#b8b8b8\",\n darkgray: \"#4e4e4e\",\n dark: \"#2b2b2b\",\n secondary: \"#284b63\",\n tertiary: \"#84a59d\",\n highlight: \"rgba(143, 159, 169, 0.15)\",\n },\n darkMode: {\n light: \"#050a18\",\n lightgray: \"#0f172a\",\n gray: \"#1e293b\",\n darkgray: \"#94a3b8\",\n dark: \"#e2e8f0\",\n secondary: \"#06b6d4\",\n tertiary: \"#3b82f6\",\n highlight: \"rgba(6, 182, 212, 0.15)\",\n },\n },\n },\n },\n plugins: {\n transformers: [\n // plugins here\n ],\n filters: [\n // filters here\n ],\n emitters: [\n // emitters here\n ],\n }\n};\n```\n\n### Step 3: Integrating with Astro\n\nNow, where Quartz ends and Astro begins is where the magic really happens. Here's how I integrated them:\n\n1. Create a new Astro project:\n\n```bash\nnpm create astro@latest my-digital-garden\ncd my-digital-garden\n```\n\n2. Set up your Astro project structure:\n\n```\nmy-digital-garden/\n├── public/\n├── src/\n│ ├── components/\n│ ├── layouts/\n│ ├── pages/\n│ │ └── index.astro\n│ └── content/ (this will point to your Quartz content)\n├── astro.config.mjs\n└── package.json\n```\n\n3. Configure Astro to work with Quartz's output:\n\n```typescript\n// astro.config.mjs\nimport { defineConfig } from 'astro/config';\n\nexport default defineConfig({\n integrations: [\n // Your integrations here\n ],\n markdown: {\n remarkPlugins: [\n // The same remark plugins used in Quartz\n ],\n rehypePlugins: [\n // The same rehype plugins used in Quartz\n ]\n }\n});\n```\n\n4. Create a component for the Obsidian graph view (similar to what I use on this blog):\n\n```astro\n---\n// Graph.astro\n---\n\n\u003Cdiv class=\"graph-container\">\n \u003Cdiv class=\"graph-visualization\">\n \u003Cdiv class=\"graph-overlay\">\u003C/div>\n \u003Cdiv class=\"graph-nodes\" id=\"obsidian-graph\">\u003C/div>\n \u003C/div>\n \u003Cdiv class=\"graph-caption\">Interactive visualization of interconnected notes\u003C/div>\n\u003C/div>\n\n\u003Cscript src=\"/blog/scripts/neural-network.js\" defer>\u003C/script>\n\n\u003Cstyle>\n .graph-container {\n width: 100%;\n height: 400px;\n position: relative;\n border-radius: 0.75rem;\n overflow: hidden;\n background: rgba(15, 23, 42, 0.6);\n border: 1px solid rgba(56, 189, 248, 0.2);\n }\n \n .graph-visualization {\n width: 100%;\n height: 100%;\n position: relative;\n }\n \n .graph-overlay {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: radial-gradient(\n circle at center,\n transparent 0%,\n rgba(15, 23, 42, 0.5) 100%\n );\n z-index: 1;\n pointer-events: none;\n }\n \n .graph-nodes {\n width: 100%;\n height: 100%;\n position: relative;\n z-index: 2;\n }\n \n .graph-caption {\n position: absolute;\n bottom: 0.75rem;\n left: 0;\n width: 100%;\n text-align: center;\n color: rgba(148, 163, 184, 0.8);\n font-size: 0.875rem;\n z-index: 3;\n }\n\u003C/style>\n```\n\n## Writing Content for Your Digital Garden\n\nNow that you have the technical setup, let's talk about how to structure your content. Here's how I approach it:\n\n### 1. Use Meaningful Frontmatter\n\nEach note should have frontmatter that helps organize and categorize it:\n\n```markdown\n---\ntitle: \"Building a Digital Garden\"\ndescription: \"How to create a connected knowledge base with Obsidian and Quartz\"\npubDate: 2023-11-05\nupdatedDate: 2024-02-10\ncategory: \"Knowledge Management\"\ntags: [\"digital-garden\", \"obsidian\", \"quartz\", \"notes\"]\n---\n```\n\n### 2. Create Meaningful Connections\n\nThe power of a digital garden comes from connections. Use Obsidian's `[wiki-links]` liberally to connect related concepts:\n\n```markdown\nI'm using the [quartz-digital-garden|Quartz framework] to power my digital garden. It works well with [obsidian-setup|my Obsidian workflow].\n```\n\n### 3. Use Consistent Structure for Your Notes\n\nI follow a template for most of my notes to maintain consistency:\n\n- Brief introduction/definition\n- Why it matters\n- Key concepts\n- Examples or code snippets\n- References to related notes\n- External resources\n\n### 4. Leverage Obsidian Features\n\nMake use of Obsidian's unique features that Quartz preserves:\n\n- **Callouts** for highlighting important information\n- **Dataview** for creating dynamic content (if using the Dataview plugin)\n- **Graphs** to visualize connections\n\n## Deploying Your Digital Garden\n\nHere's how I deploy my digital garden to Cloudflare Pages:\n\n1. **Build Configuration**:\n\n```javascript\n// Build command\nastro build\n\n// Output directory\ndist\n```\n\n2. **Automated Deployment from Git**:\n\nI have a GitHub action that publishes my content whenever I push changes:\n\n```yaml\nname: Deploy to Cloudflare Pages\n\non:\n push:\n branches: [main]\n\njobs:\n deploy:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v3\n with:\n submodules: true\n - uses: actions/setup-node@v3\n with:\n node-version: 18\n - name: Install Dependencies\n run: npm ci\n - name: Build\n run: npm run build\n - name: Deploy to Cloudflare Pages\n uses: cloudflare/pages-action@v1\n with:\n apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}\n accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}\n projectName: digital-garden\n directory: dist\n```\n\n## My Digital Garden Workflow\n\nHere's my actual workflow for maintaining my digital garden:\n\n1. **Daily note-taking** in Obsidian (private vault)\n2. **Weekly review** where I refine notes and connections\n3. **Publishing prep** where I move polished notes to my public vault\n4. **Git commit and push** which triggers the deployment\n\nThe beauty of this system is that my private thinking and public sharing use the same tools and formats, reducing friction between capturing thoughts and sharing them.\n\n## Adding Interactive Elements\n\nOne of my favorite parts of using Astro with Quartz is that I can add interactive elements to my digital garden. For example, the neural graph visualization you see on this blog:\n\n```javascript\n// Simplified version of the neural network graph code\ndocument.addEventListener('DOMContentLoaded', () => {\n const container = document.querySelector('.graph-nodes');\n if (!container) return;\n \n // Configuration\n const CONNECTION_DISTANCE = 30;\n const MIN_NODE_SIZE = 4;\n const MAX_NODE_SIZE = 12;\n \n // Fetch blog data from the same origin\n async function fetchQuartzData() {\n // In production, fetch from your actual API\n return {\n nodes: [\n {\n id: 'digital-garden',\n title: 'Digital Garden',\n tags: ['knowledge-management', 'notes'],\n category: 'concept'\n },\n // More nodes here\n ],\n links: [\n { source: 'digital-garden', target: 'obsidian' },\n // More links here\n ]\n };\n }\n \n // Create the visualization\n fetchQuartzData().then(graphData => {\n // Create nodes and connections\n // (implementation details omitted for brevity)\n });\n});\n```\n\n## Tips for a Successful Digital Garden\n\nAfter maintaining my digital garden for over a year, here are my top tips:\n\n1. **Start small** - Begin with a few well-connected notes rather than trying to publish everything at once.\n\n2. **Focus on connections** - The value is in the links between notes, not just the notes themselves.\n\n3. **Embrace imperfection** - Digital gardens are meant to grow and evolve; they're never \"finished.\"\n\n4. **Build in public** - Share your process and learnings as you go.\n\n5. **Use consistent formatting** - Makes it easier for readers to navigate your garden.\n\n## The Impact of My Digital Garden\n\nSince starting my digital garden, I've experienced several unexpected benefits:\n\n- **Clearer thinking** - Writing for an audience forces me to clarify my thoughts.\n- **Unexpected connections** - I've discovered relationships between ideas I hadn't noticed before.\n- **Community building** - I've connected with others interested in the same topics.\n- **Learning accountability** - Publishing regularly motivates me to keep learning.\n\n## Wrapping Up\n\nBuilding a digital garden with Quartz, Obsidian, and Astro has transformed how I learn and share knowledge. It's become so much more than a blog - it's a living representation of my thinking that grows more valuable with each connection I make.\n\nIf you're considering starting your own digital garden, I hope this guide gives you a solid foundation. Remember, the best garden is the one you actually tend to, so start simple and let it grow naturally over time.\n\nWhat about you? Are you maintaining a digital garden or thinking about starting one? I'd love to hear about your experience in the comments!\n\n---\n\n_This post was last updated on February 10, 2024 with information about the latest Quartz configuration options and integration with Astro._","src/content/blog/posts/quartz-digital-garden.md","c81c41cf63fd13fa",{"html":1868,"metadata":1869},"\u003Cp>I’ve been taking digital notes for decades now. From simple \u003Ccode>.txt\u003C/code> files to OneNote, Evernote, Notion, and now Obsidian. But for years, I’ve been wrestling with a question: how do I share my knowledge with others in a way that preserves the connections between ideas?\u003C/p>\n\u003Cp>Enter \u003Ca href=\"https://quartz.jzhao.xyz/\">Quartz\u003C/a> - an open-source static site generator designed specifically for transforming Obsidian vaults into interconnected digital gardens. I’ve been using it with Astro to power this very blog, and today I want to show you how you can do the same.\u003C/p>\n\u003Ch2 id=\"what-is-a-digital-garden\">What is a Digital Garden?\u003C/h2>\n\u003Cp>Before we dive into the technical stuff, let’s talk about what a digital garden actually is. Unlike traditional blogs organized chronologically, a digital garden is more like… well, a garden! It’s a collection of interconnected notes that grow over time.\u003C/p>\n\u003Cp>Think of each note as a plant. Some are seedlings (early ideas), some are in full bloom (well-developed thoughts), and others might be somewhere in between. The beauty of a digital garden is that it evolves organically, with connections forming between ideas just as they do in our brains.\u003C/p>\n\u003Ch2 id=\"why-quartz--obsidian--astro\">Why Quartz + Obsidian + Astro?\u003C/h2>\n\u003Cp>I settled on this stack after trying numerous solutions, and here’s why:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Cstrong>Obsidian\u003C/strong>: Provides a fantastic editing experience with bi-directional linking, graph views, and markdown support.\u003C/li>\n\u003Cli>\u003Cstrong>Quartz\u003C/strong>: Transforms Obsidian vaults into interconnected websites with minimal configuration.\u003C/li>\n\u003Cli>\u003Cstrong>Astro\u003C/strong>: Adds flexibility for custom layouts, components, and integrations not available in Quartz alone.\u003C/li>\n\u003C/ul>\n\u003Cp>It’s a match made in heaven - I get the best note-taking experience with Obsidian, the connection-preserving features of Quartz, and the full power of a modern web framework with Astro.\u003C/p>\n\u003Ch2 id=\"setting-up-your-digital-garden\">Setting Up Your Digital Garden\u003C/h2>\n\u003Cp>Let’s walk through how to set this up step by step.\u003C/p>\n\u003Ch3 id=\"step-1-install-obsidian-and-create-a-vault\">Step 1: Install Obsidian and Create a Vault\u003C/h3>\n\u003Cp>If you haven’t already, \u003Ca href=\"https://obsidian.md/\">download Obsidian\u003C/a> and create a new vault for your digital garden content. I recommend having a separate vault for public content to keep it clean.\u003C/p>\n\u003Ch3 id=\"step-2-set-up-quartz\">Step 2: Set Up Quartz\u003C/h3>\n\u003Cp>Quartz is essentially a template for your Obsidian content. Here’s how to get it running:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Clone the Quartz repository\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">git\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> clone\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> https://github.com/jackyzha0/quartz.git\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">cd\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> quartz\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Install dependencies\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">npm\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> install\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Copy your Obsidian vault content to the content folder\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># (or symlink it, which is what I do)\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">ln\u003C/span>\u003Cspan style=\"color:#BD93F9\"> -s\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> /path/to/your/obsidian/vault\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> content\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Once installed, you can customize your Quartz configuration in the \u003Ccode>quartz.config.ts\u003C/code> file. Here’s a snippet of mine:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"typescript\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\">// quartz.config.ts\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\">const\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> config\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#8BE9FD;font-style:italic\"> QuartzConfig\u003C/span>\u003Cspan style=\"color:#FF79C6\"> =\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> configuration\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> pageTitle\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">LaForceIT Digital Garden\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> enableSPA\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> true\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> enablePopovers\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> true\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> analytics\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> provider\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">plausible\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> baseUrl\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">blog.laforceit.com\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> ignorePatterns\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">private\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">templates\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">.obsidian\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">],\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> theme\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> typography\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> header\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Space Grotesk\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> body\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Space Grotesk\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> code\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">JetBrains Mono\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> colors\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> lightMode\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> light\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">#fafafa\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> lightgray\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">#e5e5e5\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> gray\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">#b8b8b8\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> darkgray\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">#4e4e4e\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> dark\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">#2b2b2b\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> secondary\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">#284b63\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> tertiary\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">#84a59d\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> highlight\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">rgba(143, 159, 169, 0.15)\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> darkMode\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> light\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">#050a18\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> lightgray\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">#0f172a\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> gray\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">#1e293b\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> darkgray\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">#94a3b8\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> dark\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">#e2e8f0\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> secondary\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">#06b6d4\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> tertiary\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">#3b82f6\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> highlight\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">rgba(6, 182, 212, 0.15)\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> plugins\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> transformers\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> // plugins here\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> ],\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> filters\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> // filters here\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> ],\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> emitters\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> // emitters here\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> ],\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">};\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"step-3-integrating-with-astro\">Step 3: Integrating with Astro\u003C/h3>\n\u003Cp>Now, where Quartz ends and Astro begins is where the magic really happens. Here’s how I integrated them:\u003C/p>\n\u003Col>\n\u003Cli>Create a new Astro project:\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">npm\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> create\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> astro@latest\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> my-digital-garden\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">cd\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> my-digital-garden\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Col start=\"2\">\n\u003Cli>Set up your Astro project structure:\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"plaintext\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan>my-digital-garden/\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>├── public/\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>├── src/\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>│ ├── components/\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>│ ├── layouts/\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>│ ├── pages/\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>│ │ └── index.astro\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>│ └── content/ (this will point to your Quartz content)\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>├── astro.config.mjs\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>└── package.json\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Col start=\"3\">\n\u003Cli>Configure Astro to work with Quartz’s output:\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"typescript\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\">// astro.config.mjs\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\">import\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> { defineConfig } \u003C/span>\u003Cspan style=\"color:#FF79C6\">from\u003C/span>\u003Cspan style=\"color:#E9F284\"> '\u003C/span>\u003Cspan style=\"color:#F1FA8C\">astro/config\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\">export\u003C/span>\u003Cspan style=\"color:#FF79C6\"> default\u003C/span>\u003Cspan style=\"color:#50FA7B\"> defineConfig\u003C/span>\u003Cspan style=\"color:#F8F8F2\">({\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> integrations\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> // Your integrations here\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> ],\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> markdown\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> remarkPlugins\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> // The same remark plugins used in Quartz\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> ],\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> rehypePlugins\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> // The same rehype plugins used in Quartz\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> ]\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">});\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Col start=\"4\">\n\u003Cli>Create a component for the Obsidian graph view (similar to what I use on this blog):\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"astro\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\">---\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\">// Graph.astro\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\">---\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"><\u003C/span>\u003Cspan style=\"color:#FF79C6\">div\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\"> class\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">graph-container\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> <\u003C/span>\u003Cspan style=\"color:#FF79C6\">div\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\"> class\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">graph-visualization\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> <\u003C/span>\u003Cspan style=\"color:#FF79C6\">div\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\"> class\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">graph-overlay\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">></\u003C/span>\u003Cspan style=\"color:#FF79C6\">div\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> <\u003C/span>\u003Cspan style=\"color:#FF79C6\">div\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\"> class\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">graph-nodes\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\"> id\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">obsidian-graph\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">></\u003C/span>\u003Cspan style=\"color:#FF79C6\">div\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> </\u003C/span>\u003Cspan style=\"color:#FF79C6\">div\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> <\u003C/span>\u003Cspan style=\"color:#FF79C6\">div\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\"> class\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">graph-caption\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>Interactive visualization of interconnected notes</\u003C/span>\u003Cspan style=\"color:#FF79C6\">div\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"></\u003C/span>\u003Cspan style=\"color:#FF79C6\">div\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"><\u003C/span>\u003Cspan style=\"color:#FF79C6\">script\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\"> src\u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">/blog/scripts/neural-network.js\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#50FA7B;font-style:italic\"> defer\u003C/span>\u003Cspan style=\"color:#F8F8F2\">></\u003C/span>\u003Cspan style=\"color:#FF79C6\">script\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"><\u003C/span>\u003Cspan style=\"color:#FF79C6\">style\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B;font-style:italic\"> .graph-container\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> width\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 100\u003C/span>\u003Cspan style=\"color:#FF79C6\">%\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> height\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 400\u003C/span>\u003Cspan style=\"color:#FF79C6\">px\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> position\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> relative\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> border-radius\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 0.75\u003C/span>\u003Cspan style=\"color:#FF79C6\">rem\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> overflow\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> hidden\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> background\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> rgba\u003C/span>\u003Cspan style=\"color:#F8F8F2\">(\u003C/span>\u003Cspan style=\"color:#BD93F9\">15\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#BD93F9\">23\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#BD93F9\">42\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#BD93F9\">0.6\u003C/span>\u003Cspan style=\"color:#F8F8F2\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> border\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 1\u003C/span>\u003Cspan style=\"color:#FF79C6\">px\u003C/span>\u003Cspan style=\"color:#BD93F9\"> solid\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> rgba\u003C/span>\u003Cspan style=\"color:#F8F8F2\">(\u003C/span>\u003Cspan style=\"color:#BD93F9\">56\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#BD93F9\">189\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#BD93F9\">248\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#BD93F9\">0.2\u003C/span>\u003Cspan style=\"color:#F8F8F2\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B;font-style:italic\"> .graph-visualization\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> width\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 100\u003C/span>\u003Cspan style=\"color:#FF79C6\">%\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> height\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 100\u003C/span>\u003Cspan style=\"color:#FF79C6\">%\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> position\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> relative\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B;font-style:italic\"> .graph-overlay\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> position\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> absolute\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> top\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 0\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> left\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 0\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> width\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 100\u003C/span>\u003Cspan style=\"color:#FF79C6\">%\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> height\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 100\u003C/span>\u003Cspan style=\"color:#FF79C6\">%\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> background\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> radial-gradient\u003C/span>\u003Cspan style=\"color:#F8F8F2\">(\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> circle\u003C/span>\u003Cspan style=\"color:#FF79C6\"> at\u003C/span>\u003Cspan style=\"color:#BD93F9\"> center\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\"> transparent\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 0\u003C/span>\u003Cspan style=\"color:#FF79C6\">%\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> rgba\u003C/span>\u003Cspan style=\"color:#F8F8F2\">(\u003C/span>\u003Cspan style=\"color:#BD93F9\">15\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#BD93F9\">23\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#BD93F9\">42\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#BD93F9\">0.5\u003C/span>\u003Cspan style=\"color:#F8F8F2\">) \u003C/span>\u003Cspan style=\"color:#BD93F9\">100\u003C/span>\u003Cspan style=\"color:#FF79C6\">%\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> );\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> z-index\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 1\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> pointer-events\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> none\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B;font-style:italic\"> .graph-nodes\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> width\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 100\u003C/span>\u003Cspan style=\"color:#FF79C6\">%\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> height\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 100\u003C/span>\u003Cspan style=\"color:#FF79C6\">%\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> position\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> relative\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> z-index\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 2\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B;font-style:italic\"> .graph-caption\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> position\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> absolute\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> bottom\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 0.75\u003C/span>\u003Cspan style=\"color:#FF79C6\">rem\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> left\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 0\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> width\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 100\u003C/span>\u003Cspan style=\"color:#FF79C6\">%\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> text-align\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> center\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> color\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> rgba\u003C/span>\u003Cspan style=\"color:#F8F8F2\">(\u003C/span>\u003Cspan style=\"color:#BD93F9\">148\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#BD93F9\">163\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#BD93F9\">184\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#BD93F9\">0.8\u003C/span>\u003Cspan style=\"color:#F8F8F2\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> font-size\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 0.875\u003C/span>\u003Cspan style=\"color:#FF79C6\">rem\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> z-index\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 3\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"></\u003C/span>\u003Cspan style=\"color:#FF79C6\">style\u003C/span>\u003Cspan style=\"color:#F8F8F2\">>\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"writing-content-for-your-digital-garden\">Writing Content for Your Digital Garden\u003C/h2>\n\u003Cp>Now that you have the technical setup, let’s talk about how to structure your content. Here’s how I approach it:\u003C/p>\n\u003Ch3 id=\"1-use-meaningful-frontmatter\">1. Use Meaningful Frontmatter\u003C/h3>\n\u003Cp>Each note should have frontmatter that helps organize and categorize it:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"markdown\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">---\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">title\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Building a Digital Garden\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">description\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">How to create a connected knowledge base with Obsidian and Quartz\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">pubDate\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#FFB86C\"> 2023-11-05\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">updatedDate\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#FFB86C\"> 2024-02-10\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">category\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> \"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Knowledge Management\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">tags\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">digital-garden\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">obsidian\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">quartz\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F1FA8C\">notes\u003C/span>\u003Cspan style=\"color:#E9F284\">\"\u003C/span>\u003Cspan style=\"color:#F8F8F2\">]\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">---\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"2-create-meaningful-connections\">2. Create Meaningful Connections\u003C/h3>\n\u003Cp>The power of a digital garden comes from connections. Use Obsidian’s \u003Ccode>[wiki-links]\u003C/code> liberally to connect related concepts:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"markdown\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">I'm using the [quartz-digital-garden|Quartz framework] to power my digital garden. It works well with [obsidian-setup|my Obsidian workflow].\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"3-use-consistent-structure-for-your-notes\">3. Use Consistent Structure for Your Notes\u003C/h3>\n\u003Cp>I follow a template for most of my notes to maintain consistency:\u003C/p>\n\u003Cul>\n\u003Cli>Brief introduction/definition\u003C/li>\n\u003Cli>Why it matters\u003C/li>\n\u003Cli>Key concepts\u003C/li>\n\u003Cli>Examples or code snippets\u003C/li>\n\u003Cli>References to related notes\u003C/li>\n\u003Cli>External resources\u003C/li>\n\u003C/ul>\n\u003Ch3 id=\"4-leverage-obsidian-features\">4. Leverage Obsidian Features\u003C/h3>\n\u003Cp>Make use of Obsidian’s unique features that Quartz preserves:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Cstrong>Callouts\u003C/strong> for highlighting important information\u003C/li>\n\u003Cli>\u003Cstrong>Dataview\u003C/strong> for creating dynamic content (if using the Dataview plugin)\u003C/li>\n\u003Cli>\u003Cstrong>Graphs\u003C/strong> to visualize connections\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"deploying-your-digital-garden\">Deploying Your Digital Garden\u003C/h2>\n\u003Cp>Here’s how I deploy my digital garden to Cloudflare Pages:\u003C/p>\n\u003Col>\n\u003Cli>\u003Cstrong>Build Configuration\u003C/strong>:\u003C/li>\n\u003C/ol>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"javascript\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\">// Build command\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">astro build\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\">// Output directory\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">dist\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Col start=\"2\">\n\u003Cli>\u003Cstrong>Automated Deployment from Git\u003C/strong>:\u003C/li>\n\u003C/ol>\n\u003Cp>I have a GitHub action that publishes my content whenever I push changes:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Deploy to Cloudflare Pages\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#BD93F9\">on\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> push\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> branches\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003Cspan style=\"color:#F1FA8C\">main\u003C/span>\u003Cspan style=\"color:#F8F8F2\">]\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\">jobs\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> deploy\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> runs-on\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ubuntu-latest\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> steps\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> uses\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> actions/checkout@v3\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> with\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> submodules\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> true\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> uses\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> actions/setup-node@v3\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> with\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> node-version\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 18\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Install Dependencies\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> run\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> npm ci\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Build\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> run\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> npm run build\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> -\u003C/span>\u003Cspan style=\"color:#8BE9FD\"> name\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> Deploy to Cloudflare Pages\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> uses\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> cloudflare/pages-action@v1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> with\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> apiToken\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ${{ secrets.CLOUDFLARE_API_TOKEN }}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> accountId\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> projectName\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> digital-garden\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#8BE9FD\"> directory\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> dist\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"my-digital-garden-workflow\">My Digital Garden Workflow\u003C/h2>\n\u003Cp>Here’s my actual workflow for maintaining my digital garden:\u003C/p>\n\u003Col>\n\u003Cli>\u003Cstrong>Daily note-taking\u003C/strong> in Obsidian (private vault)\u003C/li>\n\u003Cli>\u003Cstrong>Weekly review\u003C/strong> where I refine notes and connections\u003C/li>\n\u003Cli>\u003Cstrong>Publishing prep\u003C/strong> where I move polished notes to my public vault\u003C/li>\n\u003Cli>\u003Cstrong>Git commit and push\u003C/strong> which triggers the deployment\u003C/li>\n\u003C/ol>\n\u003Cp>The beauty of this system is that my private thinking and public sharing use the same tools and formats, reducing friction between capturing thoughts and sharing them.\u003C/p>\n\u003Ch2 id=\"adding-interactive-elements\">Adding Interactive Elements\u003C/h2>\n\u003Cp>One of my favorite parts of using Astro with Quartz is that I can add interactive elements to my digital garden. For example, the neural graph visualization you see on this blog:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"javascript\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\">// Simplified version of the neural network graph code\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">document.\u003C/span>\u003Cspan style=\"color:#50FA7B\">addEventListener\u003C/span>\u003Cspan style=\"color:#F8F8F2\">(\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003Cspan style=\"color:#F1FA8C\">DOMContentLoaded\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, () \u003C/span>\u003Cspan style=\"color:#FF79C6\">=>\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> const\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> container \u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> document.\u003C/span>\u003Cspan style=\"color:#50FA7B\">querySelector\u003C/span>\u003Cspan style=\"color:#F8F8F2\">(\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003Cspan style=\"color:#F1FA8C\">.graph-nodes\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003Cspan style=\"color:#F8F8F2\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> if\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> (\u003C/span>\u003Cspan style=\"color:#FF79C6\">!\u003C/span>\u003Cspan style=\"color:#F8F8F2\">container) \u003C/span>\u003Cspan style=\"color:#FF79C6\">return\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> // Configuration\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> const\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> CONNECTION_DISTANCE \u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 30\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> const\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> MIN_NODE_SIZE \u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 4\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> const\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> MAX_NODE_SIZE \u003C/span>\u003Cspan style=\"color:#FF79C6\">=\u003C/span>\u003Cspan style=\"color:#BD93F9\"> 12\u003C/span>\u003Cspan style=\"color:#F8F8F2\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> // Fetch blog data from the same origin\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> async\u003C/span>\u003Cspan style=\"color:#FF79C6\"> function\u003C/span>\u003Cspan style=\"color:#50FA7B\"> fetchQuartzData\u003C/span>\u003Cspan style=\"color:#F8F8F2\">() {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> // In production, fetch from your actual API\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF79C6\"> return\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> nodes\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> id\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> '\u003C/span>\u003Cspan style=\"color:#F1FA8C\">digital-garden\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> title\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> '\u003C/span>\u003Cspan style=\"color:#F1FA8C\">Digital Garden\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003Cspan style=\"color:#F8F8F2\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> tags\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003Cspan style=\"color:#F1FA8C\">knowledge-management\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, \u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003Cspan style=\"color:#F1FA8C\">notes\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003Cspan style=\"color:#F8F8F2\">],\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> category\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> '\u003C/span>\u003Cspan style=\"color:#F1FA8C\">concept\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> // More nodes here\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> ],\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> links\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> [\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> { source\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> '\u003C/span>\u003Cspan style=\"color:#F1FA8C\">digital-garden\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003Cspan style=\"color:#F8F8F2\">, target\u003C/span>\u003Cspan style=\"color:#FF79C6\">:\u003C/span>\u003Cspan style=\"color:#E9F284\"> '\u003C/span>\u003Cspan style=\"color:#F1FA8C\">obsidian\u003C/span>\u003Cspan style=\"color:#E9F284\">'\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> // More links here\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> ]\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> };\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> \u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> // Create the visualization\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\"> fetchQuartzData\u003C/span>\u003Cspan style=\"color:#F8F8F2\">().\u003C/span>\u003Cspan style=\"color:#50FA7B\">then\u003C/span>\u003Cspan style=\"color:#F8F8F2\">(\u003C/span>\u003Cspan style=\"color:#FFB86C;font-style:italic\">graphData\u003C/span>\u003Cspan style=\"color:#FF79C6\"> =>\u003C/span>\u003Cspan style=\"color:#F8F8F2\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> // Create nodes and connections\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"> // (implementation details omitted for brevity)\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\"> });\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F8F8F2\">});\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"tips-for-a-successful-digital-garden\">Tips for a Successful Digital Garden\u003C/h2>\n\u003Cp>After maintaining my digital garden for over a year, here are my top tips:\u003C/p>\n\u003Col>\n\u003Cli>\n\u003Cp>\u003Cstrong>Start small\u003C/strong> - Begin with a few well-connected notes rather than trying to publish everything at once.\u003C/p>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>Focus on connections\u003C/strong> - The value is in the links between notes, not just the notes themselves.\u003C/p>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>Embrace imperfection\u003C/strong> - Digital gardens are meant to grow and evolve; they’re never “finished.”\u003C/p>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>Build in public\u003C/strong> - Share your process and learnings as you go.\u003C/p>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>Use consistent formatting\u003C/strong> - Makes it easier for readers to navigate your garden.\u003C/p>\n\u003C/li>\n\u003C/ol>\n\u003Ch2 id=\"the-impact-of-my-digital-garden\">The Impact of My Digital Garden\u003C/h2>\n\u003Cp>Since starting my digital garden, I’ve experienced several unexpected benefits:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Cstrong>Clearer thinking\u003C/strong> - Writing for an audience forces me to clarify my thoughts.\u003C/li>\n\u003Cli>\u003Cstrong>Unexpected connections\u003C/strong> - I’ve discovered relationships between ideas I hadn’t noticed before.\u003C/li>\n\u003Cli>\u003Cstrong>Community building\u003C/strong> - I’ve connected with others interested in the same topics.\u003C/li>\n\u003Cli>\u003Cstrong>Learning accountability\u003C/strong> - Publishing regularly motivates me to keep learning.\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"wrapping-up\">Wrapping Up\u003C/h2>\n\u003Cp>Building a digital garden with Quartz, Obsidian, and Astro has transformed how I learn and share knowledge. It’s become so much more than a blog - it’s a living representation of my thinking that grows more valuable with each connection I make.\u003C/p>\n\u003Cp>If you’re considering starting your own digital garden, I hope this guide gives you a solid foundation. Remember, the best garden is the one you actually tend to, so start simple and let it grow naturally over time.\u003C/p>\n\u003Cp>What about you? Are you maintaining a digital garden or thinking about starting one? I’d love to hear about your experience in the comments!\u003C/p>\n\u003Chr>\n\u003Cp>\u003Cem>This post was last updated on February 10, 2024 with information about the latest Quartz configuration options and integration with Astro.\u003C/em>\u003C/p>",{"headings":1870,"localImagePaths":1888,"remoteImagePaths":1889,"frontmatter":1890,"imagePaths":1894},[1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887],{"depth":55,"slug":460,"text":461},{"depth":55,"slug":838,"text":839},{"depth":55,"slug":841,"text":842},{"depth":97,"slug":844,"text":845},{"depth":97,"slug":847,"text":848},{"depth":97,"slug":850,"text":851},{"depth":55,"slug":853,"text":854},{"depth":97,"slug":856,"text":857},{"depth":97,"slug":859,"text":860},{"depth":97,"slug":862,"text":863},{"depth":97,"slug":865,"text":866},{"depth":55,"slug":868,"text":869},{"depth":55,"slug":871,"text":872},{"depth":55,"slug":874,"text":875},{"depth":55,"slug":877,"text":878},{"depth":55,"slug":880,"text":881},{"depth":55,"slug":563,"text":564},[],[],{"title":821,"description":822,"pubDate":1891,"updatedDate":1892,"category":507,"tags":1893,"heroImage":17},["Date","2025-04-18T00:00:00.000Z"],["Date","2025-04-19T00:00:00.000Z"],[826,827,448,449,828],[],"posts/quartz-digital-garden.md","projects",["Map",1630,1898,927,1918],{"id":1630,"data":1899,"body":1622,"filePath":1902,"digest":1624,"rendered":1903,"legacyId":1917},{"title":1612,"description":1613,"pubDate":1900,"heroImage":1615,"category":1046,"draft":182,"author":1198,"github":1616,"technologies":1901},["Date","2023-10-15T00:00:00.000Z"],[1618,178,1619,1620,1621],"src/content/projects/argobox.md",{"html":1626,"metadata":1904},{"headings":1905,"localImagePaths":1911,"remoteImagePaths":1912,"frontmatter":1913,"imagePaths":1916},[1906,1907,1908,1909,1910],{"depth":52,"slug":1630,"text":1612},{"depth":55,"slug":1344,"text":1345},{"depth":55,"slug":1633,"text":1634},{"depth":55,"slug":1636,"text":1637},{"depth":55,"slug":1639,"text":1640},[],[],{"title":1612,"pubDate":1914,"description":1613,"author":1198,"heroImage":1615,"category":1046,"technologies":1915,"github":1616,"draft":182},["Date","2023-10-15T00:00:00.000Z"],[1618,178,1619,1620,1621],[],"argobox.md",{"id":927,"data":1919,"body":1757,"filePath":1922,"digest":1759,"rendered":1923,"legacyId":1932},{"title":1751,"description":1752,"pubDate":1920,"heroImage":445,"status":1754,"tech":1921},["Date","2025-04-18T00:00:00.000Z"],[828,1756],"src/content/projects/placeholder.md",{"html":1761,"metadata":1924},{"headings":1925,"localImagePaths":1927,"remoteImagePaths":1928,"frontmatter":1929,"imagePaths":1931},[1926],{"depth":52,"slug":1765,"text":1751},[],[],{"title":1751,"description":1752,"heroImage":445,"pubDate":1930,"status":1754,"tech":1921},["Date","2025-04-18T00:00:00.000Z"],[],"placeholder.md","posts",["Map",11,1935,171,1947,37,1962,1196,1977,216,2002,260,2025,379,2050,312,2080,67,2116,439,2156,500,2176,573,2208,477,2234,2249,2250,627,2293,701,2326,818,2373],{"id":11,"data":1936,"filePath":1938,"digest":26,"rendered":1939,"legacyId":36},{"title":14,"description":15,"pubDate":16,"heroImage":17,"category":18,"tags":1937,"readTime":24},[20,18,21,22,23],"src/content/posts/Test.md",{"html":28,"metadata":1940},{"headings":1941,"localImagePaths":1942,"remoteImagePaths":1943,"frontmatter":1944,"imagePaths":1946},[],[],[],{"title":14,"description":15,"pubDate":16,"heroImage":17,"category":18,"tags":1945,"readTime":24},[20,18,21,22,23],[],{"id":171,"data":1948,"body":1172,"filePath":1951,"digest":1174,"rendered":1952,"legacyId":215},{"title":174,"description":1168,"pubDate":1949,"heroImage":1170,"category":1046,"tags":1950,"draft":182},["Date","2025-04-19T00:00:00.000Z"],[180,181,73,22,636],"src/content/posts/k3s-cluster.md",{"html":1176,"metadata":1953},{"headings":1954,"localImagePaths":1956,"remoteImagePaths":1957,"frontmatter":1958,"imagePaths":1961},[1955],{"depth":52,"slug":191,"text":174},[],[],{"title":174,"pubDate":1959,"description":1168,"category":1046,"tags":1960,"draft":182,"heroImage":1170},["Date","2025-04-19T00:00:00.000Z"],[180,181,73,22,636],[],{"id":37,"data":1963,"body":44,"filePath":1965,"digest":46,"rendered":1966,"legacyId":66},{"title":40,"description":41,"pubDate":1964,"draft":43},["Date","2025-04-18T00:00:00.000Z"],"src/content/posts/README.md",{"html":48,"metadata":1967},{"headings":1968,"localImagePaths":1972,"remoteImagePaths":1973,"frontmatter":1974,"imagePaths":1976},[1969,1970,1971],{"depth":52,"slug":53,"text":40},{"depth":55,"slug":56,"text":57},{"depth":55,"slug":59,"text":60},[],[],{"title":40,"description":41,"pubDate":1975,"draft":43},["Date","2025-04-18T00:00:00.000Z"],[],{"id":1196,"data":1978,"body":1981,"filePath":1982,"digest":1983,"rendered":1984,"legacyId":2001},{"title":1190,"description":1191,"pubDate":1979,"heroImage":1193,"category":1194,"tags":1980,"draft":43,"author":1198},["Date","2023-11-20T00:00:00.000Z"],[1196,1197,223],"# Example Post\n\nThis is an example post that demonstrates the structure and formatting of a blog post on the LaForce IT blog.\n\n## Introduction\n\nWhen writing blog posts, it's important to have a clear structure that guides the reader through your content. This example post shows how to organize your content effectively.\n\n## Main Content\n\n### Code Blocks\n\nYou can include code snippets like this:\n\n```bash\n# Install dependencies\nnpm install\n\n# Start the development server\nnpm run dev\n```\n\n### Lists\n\nBullet points are great for summarizing information:\n\n- Point one about the topic\n- Point two with more details\n- Point three with a conclusion\n\nNumbered lists work well for step-by-step instructions:\n\n1. First, do this important step\n2. Then, proceed to the next action\n3. Finally, complete the process\n\n### Images\n\nYou can include images with Markdown syntax:\n\n![Alt text for the image](/images/example-image.jpg)\n\n## Conclusion\n\nThis example post demonstrates the basic elements you might include in a blog post. Feel free to use this as a template for your own posts.\n\nRemember to:\n- Use clear headings and subheadings\n- Include relevant code examples\n- Add images where helpful\n- Organize content logically","src/content/posts/example.md","8b891cdf3d659058",{"html":1985,"metadata":1986},"\u003Ch1 id=\"example-post\">Example Post\u003C/h1>\n\u003Cp>This is an example post that demonstrates the structure and formatting of a blog post on the LaForce IT blog.\u003C/p>\n\u003Ch2 id=\"introduction\">Introduction\u003C/h2>\n\u003Cp>When writing blog posts, it’s important to have a clear structure that guides the reader through your content. This example post shows how to organize your content effectively.\u003C/p>\n\u003Ch2 id=\"main-content\">Main Content\u003C/h2>\n\u003Ch3 id=\"code-blocks\">Code Blocks\u003C/h3>\n\u003Cp>You can include code snippets like this:\u003C/p>\n\u003Cpre class=\"astro-code dracula\" style=\"background-color:#282A36;color:#F8F8F2; overflow-x: auto; white-space: pre-wrap; word-wrap: break-word;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Install dependencies\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">npm\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> install\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6272A4\"># Start the development server\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#50FA7B\">npm\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> run\u003C/span>\u003Cspan style=\"color:#F1FA8C\"> dev\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"lists\">Lists\u003C/h3>\n\u003Cp>Bullet points are great for summarizing information:\u003C/p>\n\u003Cul>\n\u003Cli>Point one about the topic\u003C/li>\n\u003Cli>Point two with more details\u003C/li>\n\u003Cli>Point three with a conclusion\u003C/li>\n\u003C/ul>\n\u003Cp>Numbered lists work well for step-by-step instructions:\u003C/p>\n\u003Col>\n\u003Cli>First, do this important step\u003C/li>\n\u003Cli>Then, proceed to the next action\u003C/li>\n\u003Cli>Finally, complete the process\u003C/li>\n\u003C/ol>\n\u003Ch3 id=\"images\">Images\u003C/h3>\n\u003Cp>You can include images with Markdown syntax:\u003C/p>\n\u003Cp>\u003Cimg src=\"/images/example-image.jpg\" alt=\"Alt text for the image\">\u003C/p>\n\u003Ch2 id=\"conclusion\">Conclusion\u003C/h2>\n\u003Cp>This example post demonstrates the basic elements you might include in a blog post. Feel free to use this as a template for your own posts.\u003C/p>\n\u003Cp>Remember to:\u003C/p>\n\u003Cul>\n\u003Cli>Use clear headings and subheadings\u003C/li>\n\u003Cli>Include relevant code examples\u003C/li>\n\u003Cli>Add images where helpful\u003C/li>\n\u003Cli>Organize content logically\u003C/li>\n\u003C/ul>",{"headings":1987,"localImagePaths":1995,"remoteImagePaths":1996,"frontmatter":1997,"imagePaths":2000},[1988,1989,1990,1991,1992,1993,1994],{"depth":52,"slug":1207,"text":1190},{"depth":55,"slug":899,"text":1209},{"depth":55,"slug":1211,"text":1212},{"depth":97,"slug":1214,"text":1215},{"depth":97,"slug":1217,"text":1218},{"depth":97,"slug":1220,"text":1221},{"depth":55,"slug":162,"text":163},[],[],{"title":1190,"pubDate":1998,"description":1191,"author":1198,"heroImage":1193,"category":1194,"tags":1999,"draft":43},["Date","2023-11-20T00:00:00.000Z"],[1196,1197,223],[],"example.md",{"id":216,"data":2003,"body":225,"filePath":2006,"digest":227,"rendered":2007,"legacyId":259},{"title":219,"description":220,"pubDate":2004,"heroImage":177,"category":180,"tags":2005,"readTime":224},["Date","2025-04-19T00:00:00.000Z"],[180,181,22,223],"src/content/posts/k3s-installation-guide.md",{"html":229,"metadata":2008},{"headings":2009,"localImagePaths":2019,"remoteImagePaths":2020,"frontmatter":2021,"imagePaths":2024},[2010,2011,2012,2013,2014,2015,2016,2017,2018],{"depth":52,"slug":216,"text":219},{"depth":55,"slug":193,"text":194},{"depth":55,"slug":235,"text":236},{"depth":55,"slug":238,"text":239},{"depth":97,"slug":241,"text":242},{"depth":97,"slug":244,"text":245},{"depth":55,"slug":247,"text":248},{"depth":55,"slug":250,"text":251},{"depth":55,"slug":208,"text":209},[],[],{"title":219,"description":220,"pubDate":2022,"heroImage":177,"category":180,"tags":2023,"readTime":224},["Date","2025-04-19T00:00:00.000Z"],[180,181,22,223],[],{"id":260,"data":2026,"body":273,"filePath":2029,"digest":275,"rendered":2030,"legacyId":311},{"title":263,"description":264,"pubDate":2027,"heroImage":17,"category":266,"tags":2028,"readTime":272},["Date","2025-04-19T00:00:00.000Z"],[180,268,269,270,271],"src/content/posts/gitops-with-flux-cd.md",{"html":277,"metadata":2031},{"headings":2032,"localImagePaths":2044,"remoteImagePaths":2045,"frontmatter":2046,"imagePaths":2049},[2033,2034,2035,2036,2037,2038,2039,2040,2041,2042,2043],{"depth":52,"slug":260,"text":263},{"depth":55,"slug":282,"text":283},{"depth":55,"slug":285,"text":286},{"depth":55,"slug":94,"text":95},{"depth":97,"slug":193,"text":194},{"depth":97,"slug":290,"text":291},{"depth":55,"slug":293,"text":294},{"depth":55,"slug":296,"text":297},{"depth":97,"slug":299,"text":300},{"depth":97,"slug":302,"text":303},{"depth":55,"slug":162,"text":163},[],[],{"title":263,"description":264,"pubDate":2047,"heroImage":17,"category":266,"tags":2048,"readTime":272},["Date","2025-04-19T00:00:00.000Z"],[180,268,269,270,271],[],{"id":379,"data":2051,"body":384,"filePath":2054,"digest":386,"rendered":2055,"legacyId":438},{"title":14,"description":15,"pubDate":2052,"heroImage":17,"category":18,"tags":2053,"readTime":24},["Date","2025-04-19T00:00:00.000Z"],[20,18,21,22,23],"src/content/posts/cloudflare-tunnel-setup.md",{"html":388,"metadata":2056},{"headings":2057,"localImagePaths":2074,"remoteImagePaths":2075,"frontmatter":2076,"imagePaths":2079},[2058,2059,2060,2061,2062,2063,2064,2065,2066,2067,2068,2069,2070,2071,2072,2073],{"depth":52,"slug":392,"text":14},{"depth":55,"slug":394,"text":395},{"depth":55,"slug":193,"text":194},{"depth":55,"slug":398,"text":399},{"depth":97,"slug":401,"text":402},{"depth":97,"slug":404,"text":405},{"depth":97,"slug":407,"text":408},{"depth":97,"slug":410,"text":411},{"depth":97,"slug":413,"text":414},{"depth":97,"slug":416,"text":417},{"depth":55,"slug":419,"text":420},{"depth":55,"slug":422,"text":423},{"depth":55,"slug":361,"text":362},{"depth":97,"slug":426,"text":427},{"depth":97,"slug":429,"text":430},{"depth":55,"slug":162,"text":163},[],[],{"title":14,"description":15,"pubDate":2077,"heroImage":17,"category":18,"tags":2078,"readTime":24},["Date","2025-04-19T00:00:00.000Z"],[20,18,21,22,23],[],{"id":312,"data":2081,"body":1430,"filePath":2084,"digest":1432,"rendered":2085,"legacyId":378},{"title":1425,"description":1426,"pubDate":2082,"heroImage":17,"category":266,"tags":2083,"readTime":1429},["Date","2025-04-19T00:00:00.000Z"],[180,323,321,322,324],"src/content/posts/prometheus-monitoring.md",{"html":1434,"metadata":2086},{"headings":2087,"localImagePaths":2110,"remoteImagePaths":2111,"frontmatter":2112,"imagePaths":2115},[2088,2089,2090,2091,2092,2093,2094,2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2108,2109],{"depth":52,"slug":1438,"text":1425},{"depth":55,"slug":1440,"text":1441},{"depth":55,"slug":1443,"text":1444},{"depth":55,"slug":193,"text":194},{"depth":55,"slug":339,"text":1447},{"depth":97,"slug":1449,"text":1450},{"depth":97,"slug":1452,"text":1453},{"depth":97,"slug":1455,"text":1456},{"depth":97,"slug":1458,"text":1459},{"depth":97,"slug":1461,"text":1462},{"depth":55,"slug":1464,"text":1465},{"depth":97,"slug":1467,"text":1468},{"depth":97,"slug":322,"text":345},{"depth":97,"slug":1471,"text":1472},{"depth":55,"slug":1474,"text":1475},{"depth":55,"slug":1477,"text":1478},{"depth":97,"slug":1480,"text":1481},{"depth":97,"slug":1483,"text":1484},{"depth":55,"slug":1486,"text":1487},{"depth":55,"slug":364,"text":365},{"depth":97,"slug":367,"text":368},{"depth":55,"slug":162,"text":163},[],[],{"title":1425,"description":1426,"pubDate":2113,"heroImage":17,"category":266,"tags":2114,"readTime":1429},["Date","2025-04-19T00:00:00.000Z"],[180,323,321,322,324],[],{"id":67,"data":2117,"body":78,"filePath":2120,"digest":80,"rendered":2121,"legacyId":170},{"title":70,"description":71,"pubDate":2118,"heroImage":17,"category":73,"tags":2119,"readTime":77},["Date","2025-04-19T00:00:00.000Z"],[75,76,22,73],"src/content/posts/proxmox-setup-guide.md",{"html":82,"metadata":2122},{"headings":2123,"localImagePaths":2150,"remoteImagePaths":2151,"frontmatter":2152,"imagePaths":2155},[2124,2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2137,2138,2139,2140,2141,2142,2143,2144,2145,2146,2147,2148,2149],{"depth":52,"slug":86,"text":70},{"depth":55,"slug":88,"text":89},{"depth":55,"slug":91,"text":92},{"depth":55,"slug":94,"text":95},{"depth":97,"slug":98,"text":99},{"depth":97,"slug":101,"text":102},{"depth":97,"slug":104,"text":105},{"depth":55,"slug":107,"text":108},{"depth":97,"slug":110,"text":111},{"depth":97,"slug":113,"text":114},{"depth":97,"slug":116,"text":117},{"depth":119,"slug":120,"text":121},{"depth":119,"slug":123,"text":124},{"depth":97,"slug":126,"text":127},{"depth":119,"slug":129,"text":130},{"depth":119,"slug":132,"text":133},{"depth":55,"slug":135,"text":136},{"depth":97,"slug":138,"text":139},{"depth":97,"slug":141,"text":142},{"depth":55,"slug":144,"text":145},{"depth":97,"slug":147,"text":148},{"depth":55,"slug":150,"text":151},{"depth":97,"slug":153,"text":154},{"depth":97,"slug":156,"text":157},{"depth":97,"slug":159,"text":160},{"depth":55,"slug":162,"text":163},[],[],{"title":70,"description":71,"pubDate":2153,"heroImage":17,"category":73,"tags":2154,"readTime":77},["Date","2025-04-19T00:00:00.000Z"],[75,76,22,73],[],{"id":439,"data":2157,"body":1566,"filePath":2160,"digest":1568,"rendered":2161,"legacyId":476},{"title":442,"pubDate":2158,"heroImage":17,"tags":2159,"draft":182},["Date","2025-04-19T00:00:00.000Z"],[9,1565,448],"src/content/posts/starting-my-digital-garden.md",{"html":1570,"metadata":2162},{"headings":2163,"localImagePaths":2170,"remoteImagePaths":2171,"frontmatter":2172,"imagePaths":2175},[2164,2165,2166,2167,2168,2169],{"depth":52,"slug":439,"text":442},{"depth":55,"slug":899,"text":1209},{"depth":55,"slug":1576,"text":1577},{"depth":55,"slug":463,"text":464},{"depth":55,"slug":1580,"text":1581},{"depth":55,"slug":1583,"text":1584},[],[],{"title":442,"pubDate":2173,"tags":2174,"draft":182,"heroImage":17},["Date","2025-04-19T00:00:00.000Z"],[9,1565,448],[],{"id":500,"data":2177,"body":512,"filePath":2181,"digest":514,"rendered":2182,"legacyId":572},{"title":503,"description":504,"pubDate":2178,"updatedDate":2179,"heroImage":17,"category":507,"tags":2180},["Date","2025-04-19T00:00:00.000Z"],["Date","2025-04-18T00:00:00.000Z"],[509,510,511,266,180],"src/content/posts/gitea-self-hosted-git.md",{"html":516,"metadata":2183},{"headings":2184,"localImagePaths":2201,"remoteImagePaths":2202,"frontmatter":2203,"imagePaths":2207},[2185,2186,2187,2188,2189,2190,2191,2192,2193,2194,2195,2196,2197,2198,2199,2200],{"depth":55,"slug":520,"text":521},{"depth":55,"slug":523,"text":524},{"depth":97,"slug":526,"text":527},{"depth":97,"slug":529,"text":530},{"depth":55,"slug":532,"text":533},{"depth":55,"slug":535,"text":536},{"depth":97,"slug":538,"text":539},{"depth":97,"slug":541,"text":542},{"depth":97,"slug":544,"text":545},{"depth":55,"slug":547,"text":548},{"depth":97,"slug":550,"text":551},{"depth":97,"slug":553,"text":554},{"depth":97,"slug":556,"text":557},{"depth":55,"slug":422,"text":423},{"depth":55,"slug":560,"text":561},{"depth":55,"slug":563,"text":564},[],[],{"title":503,"description":504,"pubDate":2204,"updatedDate":2205,"category":507,"tags":2206,"heroImage":17},["Date","2025-04-19T00:00:00.000Z"],["Date","2025-04-18T00:00:00.000Z"],[509,510,511,266,180],[],{"id":573,"data":2209,"body":584,"filePath":2213,"digest":586,"rendered":2214,"legacyId":626},{"title":576,"description":577,"pubDate":2210,"updatedDate":2211,"heroImage":17,"category":507,"tags":2212},["Date","2025-04-19T00:00:00.000Z"],["Date","2025-04-18T00:00:00.000Z"],[581,511,180,582,583],"src/content/posts/filebrowser-setup.md",{"html":588,"metadata":2215},{"headings":2216,"localImagePaths":2227,"remoteImagePaths":2228,"frontmatter":2229,"imagePaths":2233},[2217,2218,2219,2220,2221,2222,2223,2224,2225,2226],{"depth":55,"slug":592,"text":593},{"depth":55,"slug":595,"text":596},{"depth":97,"slug":598,"text":599},{"depth":97,"slug":601,"text":602},{"depth":55,"slug":604,"text":605},{"depth":97,"slug":607,"text":608},{"depth":55,"slug":610,"text":611},{"depth":55,"slug":613,"text":614},{"depth":55,"slug":616,"text":617},{"depth":55,"slug":563,"text":564},[],[],{"title":576,"description":577,"pubDate":2230,"updatedDate":2231,"category":507,"tags":2232,"heroImage":17},["Date","2025-04-19T00:00:00.000Z"],["Date","2025-04-18T00:00:00.000Z"],[581,511,180,582,583],[],{"id":477,"data":2235,"body":485,"filePath":2238,"digest":487,"rendered":2239,"legacyId":499},{"title":480,"description":481,"pubDate":2236,"heroImage":17,"category":483,"tags":2237,"draft":43},["Date","2024-03-20T00:00:00.000Z"],[11],"src/content/posts/test-post.md",{"html":489,"metadata":2240},{"headings":2241,"localImagePaths":2243,"remoteImagePaths":2244,"frontmatter":2245,"imagePaths":2248},[2242],{"depth":52,"slug":477,"text":480},[],[],{"title":480,"pubDate":2246,"description":481,"category":483,"tags":2247,"draft":43,"heroImage":17},["Date","2024-03-20T00:00:00.000Z"],[11],[],"configs/k3s-cluster-config",{"id":2249,"data":2251,"body":1657,"filePath":2254,"digest":1659,"rendered":2255,"legacyId":2292},{"title":1651,"description":1652,"pubDate":2252,"heroImage":1654,"category":1046,"tags":2253,"draft":43,"author":1198},["Date","2023-11-15T00:00:00.000Z"],[180,181,73,1656,22,21],"src/content/posts/configs/k3s-cluster-config.md",{"html":1661,"metadata":2256},{"headings":2257,"localImagePaths":2286,"remoteImagePaths":2287,"frontmatter":2288,"imagePaths":2291},[2258,2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285],{"depth":52,"slug":1665,"text":1651},{"depth":55,"slug":1667,"text":1668},{"depth":55,"slug":899,"text":1209},{"depth":55,"slug":1671,"text":1672},{"depth":97,"slug":1674,"text":1675},{"depth":97,"slug":1677,"text":1678},{"depth":55,"slug":1680,"text":1681},{"depth":97,"slug":1683,"text":1684},{"depth":97,"slug":1686,"text":1687},{"depth":55,"slug":1689,"text":1690},{"depth":97,"slug":1692,"text":1693},{"depth":97,"slug":1695,"text":1696},{"depth":55,"slug":1698,"text":1699},{"depth":97,"slug":1701,"text":1702},{"depth":97,"slug":1704,"text":1705},{"depth":55,"slug":1707,"text":1708},{"depth":97,"slug":1710,"text":1711},{"depth":97,"slug":1713,"text":1714},{"depth":55,"slug":1716,"text":1717},{"depth":97,"slug":1719,"text":1720},{"depth":97,"slug":1722,"text":1723},{"depth":55,"slug":1725,"text":1726},{"depth":97,"slug":1728,"text":1729},{"depth":97,"slug":1731,"text":1732},{"depth":55,"slug":364,"text":365},{"depth":97,"slug":1735,"text":1736},{"depth":97,"slug":1738,"text":1739},{"depth":55,"slug":162,"text":163},[],[],{"title":1651,"pubDate":2289,"description":1652,"author":1198,"heroImage":1654,"category":1046,"tags":2290,"draft":43},["Date","2023-11-15T00:00:00.000Z"],[180,181,73,1656,22,21],[],"configs/k3s-cluster-config.md",{"id":627,"data":2294,"body":637,"filePath":2298,"digest":639,"rendered":2299,"legacyId":700},{"title":630,"description":631,"pubDate":2295,"updatedDate":2296,"heroImage":17,"category":507,"tags":2297},["Date","2025-04-19T00:00:00.000Z"],["Date","2025-04-18T00:00:00.000Z"],[635,180,181,266,636],"src/content/posts/rancher-kubernetes-management.md",{"html":641,"metadata":2300},{"headings":2301,"localImagePaths":2319,"remoteImagePaths":2320,"frontmatter":2321,"imagePaths":2325},[2302,2303,2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318],{"depth":55,"slug":645,"text":646},{"depth":55,"slug":648,"text":649},{"depth":97,"slug":651,"text":652},{"depth":97,"slug":654,"text":655},{"depth":55,"slug":657,"text":658},{"depth":55,"slug":660,"text":661},{"depth":55,"slug":663,"text":664},{"depth":55,"slug":666,"text":667},{"depth":55,"slug":669,"text":670},{"depth":55,"slug":672,"text":673},{"depth":55,"slug":675,"text":676},{"depth":55,"slug":678,"text":679},{"depth":97,"slug":681,"text":682},{"depth":97,"slug":684,"text":685},{"depth":97,"slug":687,"text":688},{"depth":55,"slug":690,"text":691},{"depth":55,"slug":563,"text":564},[],[],{"title":630,"description":631,"pubDate":2322,"updatedDate":2323,"category":507,"tags":2324,"heroImage":17},["Date","2025-04-19T00:00:00.000Z"],["Date","2025-04-18T00:00:00.000Z"],[635,180,181,266,636],[],{"id":701,"data":2327,"body":712,"filePath":2331,"digest":714,"rendered":2332,"legacyId":817},{"title":704,"description":705,"pubDate":2328,"updatedDate":2329,"heroImage":17,"category":507,"tags":2330},["Date","2023-04-18T00:00:00.000Z"],["Date","2024-04-19T00:00:00.000Z"],[709,710,511,711,22],"src/content/posts/vscode-server-remote-development.md",{"html":716,"metadata":2333},{"headings":2334,"localImagePaths":2366,"remoteImagePaths":2367,"frontmatter":2368,"imagePaths":2372},[2335,2336,2337,2338,2339,2340,2341,2342,2343,2344,2345,2346,2347,2348,2349,2350,2351,2352,2353,2354,2355,2356,2357,2358,2359,2360,2361,2362,2363,2364,2365],{"depth":55,"slug":720,"text":721},{"depth":55,"slug":723,"text":724},{"depth":97,"slug":726,"text":727},{"depth":97,"slug":729,"text":730},{"depth":97,"slug":732,"text":733},{"depth":55,"slug":735,"text":736},{"depth":97,"slug":738,"text":739},{"depth":97,"slug":741,"text":742},{"depth":97,"slug":744,"text":745},{"depth":55,"slug":747,"text":748},{"depth":97,"slug":750,"text":751},{"depth":97,"slug":753,"text":754},{"depth":97,"slug":756,"text":757},{"depth":55,"slug":759,"text":760},{"depth":97,"slug":762,"text":763},{"depth":97,"slug":765,"text":766},{"depth":97,"slug":768,"text":769},{"depth":55,"slug":771,"text":772},{"depth":97,"slug":774,"text":775},{"depth":97,"slug":777,"text":778},{"depth":97,"slug":780,"text":781},{"depth":55,"slug":783,"text":784},{"depth":97,"slug":786,"text":787},{"depth":97,"slug":789,"text":790},{"depth":97,"slug":792,"text":793},{"depth":55,"slug":795,"text":796},{"depth":97,"slug":798,"text":799},{"depth":97,"slug":801,"text":802},{"depth":97,"slug":804,"text":805},{"depth":55,"slug":807,"text":808},{"depth":55,"slug":563,"text":564},[],[],{"title":704,"description":705,"pubDate":2369,"updatedDate":2370,"category":507,"tags":2371,"heroImage":17},["Date","2023-04-18T00:00:00.000Z"],["Date","2024-04-19T00:00:00.000Z"],[709,710,511,711,22],[],{"id":818,"data":2374,"body":1864,"filePath":2378,"digest":1866,"rendered":2379,"legacyId":890},{"title":821,"description":822,"pubDate":2375,"updatedDate":2376,"heroImage":17,"category":507,"tags":2377},["Date","2025-04-18T00:00:00.000Z"],["Date","2025-04-19T00:00:00.000Z"],[826,827,448,449,828],"src/content/posts/quartz-digital-garden.md",{"html":1868,"metadata":2380},{"headings":2381,"localImagePaths":2399,"remoteImagePaths":2400,"frontmatter":2401,"imagePaths":2405},[2382,2383,2384,2385,2386,2387,2388,2389,2390,2391,2392,2393,2394,2395,2396,2397,2398],{"depth":55,"slug":460,"text":461},{"depth":55,"slug":838,"text":839},{"depth":55,"slug":841,"text":842},{"depth":97,"slug":844,"text":845},{"depth":97,"slug":847,"text":848},{"depth":97,"slug":850,"text":851},{"depth":55,"slug":853,"text":854},{"depth":97,"slug":856,"text":857},{"depth":97,"slug":859,"text":860},{"depth":97,"slug":862,"text":863},{"depth":97,"slug":865,"text":866},{"depth":55,"slug":868,"text":869},{"depth":55,"slug":871,"text":872},{"depth":55,"slug":874,"text":875},{"depth":55,"slug":877,"text":878},{"depth":55,"slug":880,"text":881},{"depth":55,"slug":563,"text":564},[],[],{"title":821,"description":822,"pubDate":2402,"updatedDate":2403,"category":507,"tags":2404,"heroImage":17},["Date","2025-04-18T00:00:00.000Z"],["Date","2025-04-19T00:00:00.000Z"],[826,827,448,449,828],[],"configurations",["Map",2408,2409],"git-symlinks-setup",{"id":2408,"data":2410,"body":1334,"filePath":2413,"digest":1336,"rendered":2414,"legacyId":2438},{"title":1327,"description":1328,"pubDate":2411,"heroImage":1330,"category":1331,"tags":2412,"author":1198},["Date","2023-11-01T00:00:00.000Z"],[510,827,1333,271],"src/content/configurations/git-symlinks-setup.md",{"html":1338,"metadata":2415},{"headings":2416,"localImagePaths":2432,"remoteImagePaths":2433,"frontmatter":2434,"imagePaths":2437},[2417,2418,2419,2420,2421,2422,2423,2424,2425,2426,2427,2428,2429,2430,2431],{"depth":52,"slug":1342,"text":1327},{"depth":55,"slug":1344,"text":1345},{"depth":55,"slug":1347,"text":1348},{"depth":55,"slug":1350,"text":1351},{"depth":97,"slug":1353,"text":1354},{"depth":97,"slug":1356,"text":1357},{"depth":55,"slug":1359,"text":1360},{"depth":97,"slug":1362,"text":1363},{"depth":97,"slug":1365,"text":1366},{"depth":55,"slug":1368,"text":1369},{"depth":55,"slug":1371,"text":1372},{"depth":55,"slug":1374,"text":1375},{"depth":55,"slug":364,"text":365},{"depth":55,"slug":1378,"text":1379},{"depth":55,"slug":1381,"text":1382},[],[],{"title":1327,"pubDate":2435,"description":1328,"author":1198,"heroImage":1330,"category":1331,"tags":2436},["Date","2023-11-01T00:00:00.000Z"],[510,827,1333,271],[],"git-symlinks-setup.md"] \ No newline at end of file diff --git a/.astro/settings.json b/.astro/settings.json new file mode 100644 index 0000000..0499836 --- /dev/null +++ b/.astro/settings.json @@ -0,0 +1,5 @@ +{ + "_variables": { + "lastUpdateCheck": 1745122883007 + } +} \ No newline at end of file diff --git a/.astro/types.d.ts b/.astro/types.d.ts new file mode 100644 index 0000000..bd0091a --- /dev/null +++ b/.astro/types.d.ts @@ -0,0 +1,329 @@ +declare module 'astro:content' { + interface Render { + '.mdx': Promise<{ + Content: import('astro').MarkdownInstance<{}>['Content']; + headings: import('astro').MarkdownHeading[]; + remarkPluginFrontmatter: Record; + }>; + } +} + +declare module 'astro:content' { + interface Render { + '.md': Promise<{ + Content: import('astro').MarkdownInstance<{}>['Content']; + headings: import('astro').MarkdownHeading[]; + remarkPluginFrontmatter: Record; + }>; + } +} + +declare module 'astro:content' { + export { z } from 'astro/zod'; + + type Flatten = T extends { [K: string]: infer U } ? U : never; + + export type CollectionKey = keyof AnyEntryMap; + export type CollectionEntry = Flatten; + + export type ContentCollectionKey = keyof ContentEntryMap; + export type DataCollectionKey = keyof DataEntryMap; + + // This needs to be in sync with ImageMetadata + export type ImageFunction = () => import('astro/zod').ZodObject<{ + src: import('astro/zod').ZodString; + width: import('astro/zod').ZodNumber; + height: import('astro/zod').ZodNumber; + format: import('astro/zod').ZodUnion< + [ + import('astro/zod').ZodLiteral<'png'>, + import('astro/zod').ZodLiteral<'jpg'>, + import('astro/zod').ZodLiteral<'jpeg'>, + import('astro/zod').ZodLiteral<'tiff'>, + import('astro/zod').ZodLiteral<'webp'>, + import('astro/zod').ZodLiteral<'gif'>, + import('astro/zod').ZodLiteral<'svg'>, + import('astro/zod').ZodLiteral<'avif'>, + ] + >; + }>; + + type BaseSchemaWithoutEffects = + | import('astro/zod').AnyZodObject + | import('astro/zod').ZodUnion<[BaseSchemaWithoutEffects, ...BaseSchemaWithoutEffects[]]> + | import('astro/zod').ZodDiscriminatedUnion + | import('astro/zod').ZodIntersection; + + type BaseSchema = + | BaseSchemaWithoutEffects + | import('astro/zod').ZodEffects; + + export type SchemaContext = { image: ImageFunction }; + + type DataCollectionConfig = { + type: 'data'; + schema?: S | ((context: SchemaContext) => S); + }; + + type ContentCollectionConfig = { + type?: 'content'; + schema?: S | ((context: SchemaContext) => S); + }; + + type CollectionConfig = ContentCollectionConfig | DataCollectionConfig; + + export function defineCollection( + input: CollectionConfig + ): CollectionConfig; + + type AllValuesOf = T extends any ? T[keyof T] : never; + type ValidContentEntrySlug = AllValuesOf< + ContentEntryMap[C] + >['slug']; + + export function getEntryBySlug< + C extends keyof ContentEntryMap, + E extends ValidContentEntrySlug | (string & {}), + >( + collection: C, + // Note that this has to accept a regular string too, for SSR + entrySlug: E + ): E extends ValidContentEntrySlug + ? Promise> + : Promise | undefined>; + + export function getDataEntryById( + collection: C, + entryId: E + ): Promise>; + + export function getCollection>( + collection: C, + filter?: (entry: CollectionEntry) => entry is E + ): Promise; + export function getCollection( + collection: C, + filter?: (entry: CollectionEntry) => unknown + ): Promise[]>; + + export function getEntry< + C extends keyof ContentEntryMap, + E extends ValidContentEntrySlug | (string & {}), + >(entry: { + collection: C; + slug: E; + }): E extends ValidContentEntrySlug + ? Promise> + : Promise | undefined>; + export function getEntry< + C extends keyof DataEntryMap, + E extends keyof DataEntryMap[C] | (string & {}), + >(entry: { + collection: C; + id: E; + }): E extends keyof DataEntryMap[C] + ? Promise + : Promise | undefined>; + export function getEntry< + C extends keyof ContentEntryMap, + E extends ValidContentEntrySlug | (string & {}), + >( + collection: C, + slug: E + ): E extends ValidContentEntrySlug + ? Promise> + : Promise | undefined>; + export function getEntry< + C extends keyof DataEntryMap, + E extends keyof DataEntryMap[C] | (string & {}), + >( + collection: C, + id: E + ): E extends keyof DataEntryMap[C] + ? Promise + : Promise | undefined>; + + /** Resolve an array of entry references from the same collection */ + export function getEntries( + entries: { + collection: C; + slug: ValidContentEntrySlug; + }[] + ): Promise[]>; + export function getEntries( + entries: { + collection: C; + id: keyof DataEntryMap[C]; + }[] + ): Promise[]>; + + export function reference( + collection: C + ): import('astro/zod').ZodEffects< + import('astro/zod').ZodString, + C extends keyof ContentEntryMap + ? { + collection: C; + slug: ValidContentEntrySlug; + } + : { + collection: C; + id: keyof DataEntryMap[C]; + } + >; + // Allow generic `string` to avoid excessive type errors in the config + // if `dev` is not running to update as you edit. + // Invalid collection names will be caught at build time. + export function reference( + collection: C + ): import('astro/zod').ZodEffects; + + type ReturnTypeOrOriginal = T extends (...args: any[]) => infer R ? R : T; + type InferEntrySchema = import('astro/zod').infer< + ReturnTypeOrOriginal['schema']> + >; + + type ContentEntryMap = { + "configurations": { +"git-symlinks-setup.md": { + id: "git-symlinks-setup.md"; + slug: "git-symlinks-setup"; + body: string; + collection: "configurations"; + data: InferEntrySchema<"configurations"> +} & { render(): Render[".md"] }; +}; +"posts": { +"README.md": { + id: "README.md"; + slug: "readme"; + body: string; + collection: "posts"; + data: InferEntrySchema<"posts"> +} & { render(): Render[".md"] }; +"Test.md": { + id: "Test.md"; + slug: "test"; + body: string; + collection: "posts"; + data: InferEntrySchema<"posts"> +} & { render(): Render[".md"] }; +"cloudflare-tunnel-setup.md": { + id: "cloudflare-tunnel-setup.md"; + slug: "cloudflare-tunnel-setup"; + body: string; + collection: "posts"; + data: InferEntrySchema<"posts"> +} & { render(): Render[".md"] }; +"filebrowser-setup.md": { + id: "filebrowser-setup.md"; + slug: "filebrowser-setup"; + body: string; + collection: "posts"; + data: InferEntrySchema<"posts"> +} & { render(): Render[".md"] }; +"gitea-self-hosted-git.md": { + id: "gitea-self-hosted-git.md"; + slug: "gitea-self-hosted-git"; + body: string; + collection: "posts"; + data: InferEntrySchema<"posts"> +} & { render(): Render[".md"] }; +"gitops-with-flux-cd.md": { + id: "gitops-with-flux-cd.md"; + slug: "gitops-with-flux-cd"; + body: string; + collection: "posts"; + data: InferEntrySchema<"posts"> +} & { render(): Render[".md"] }; +"k3s-cluster.md": { + id: "k3s-cluster.md"; + slug: "k3s-cluster"; + body: string; + collection: "posts"; + data: InferEntrySchema<"posts"> +} & { render(): Render[".md"] }; +"k3s-installation-guide.md": { + id: "k3s-installation-guide.md"; + slug: "k3s-installation-guide"; + body: string; + collection: "posts"; + data: InferEntrySchema<"posts"> +} & { render(): Render[".md"] }; +"prometheus-monitoring.md": { + id: "prometheus-monitoring.md"; + slug: "prometheus-monitoring"; + body: string; + collection: "posts"; + data: InferEntrySchema<"posts"> +} & { render(): Render[".md"] }; +"proxmox-setup-guide.md": { + id: "proxmox-setup-guide.md"; + slug: "proxmox-setup-guide"; + body: string; + collection: "posts"; + data: InferEntrySchema<"posts"> +} & { render(): Render[".md"] }; +"quartz-digital-garden.md": { + id: "quartz-digital-garden.md"; + slug: "quartz-digital-garden"; + body: string; + collection: "posts"; + data: InferEntrySchema<"posts"> +} & { render(): Render[".md"] }; +"rancher-kubernetes-management.md": { + id: "rancher-kubernetes-management.md"; + slug: "rancher-kubernetes-management"; + body: string; + collection: "posts"; + data: InferEntrySchema<"posts"> +} & { render(): Render[".md"] }; +"starting-my-digital-garden.md": { + id: "starting-my-digital-garden.md"; + slug: "starting-my-digital-garden"; + body: string; + collection: "posts"; + data: InferEntrySchema<"posts"> +} & { render(): Render[".md"] }; +"test-post.md": { + id: "test-post.md"; + slug: "test-post"; + body: string; + collection: "posts"; + data: InferEntrySchema<"posts"> +} & { render(): Render[".md"] }; +"vscode-server-remote-development.md": { + id: "vscode-server-remote-development.md"; + slug: "vscode-server-remote-development"; + body: string; + collection: "posts"; + data: InferEntrySchema<"posts"> +} & { render(): Render[".md"] }; +}; +"projects": { +"argobox.md": { + id: "argobox.md"; + slug: "argobox"; + body: string; + collection: "projects"; + data: InferEntrySchema<"projects"> +} & { render(): Render[".md"] }; +"placeholder.md": { + id: "placeholder.md"; + slug: "placeholder"; + body: string; + collection: "projects"; + data: InferEntrySchema<"projects"> +} & { render(): Render[".md"] }; +}; + + }; + + type DataEntryMap = { + + }; + + type AnyEntryMap = ContentEntryMap & DataEntryMap; + + type ContentConfig = typeof import("../src/content/config"); +} diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..e69de29 diff --git a/.gitattributes b/.gitattributes index 2338787..f49a3d8 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,6 +1,8 @@ # Handle symbolic links as real content +public/blog/* !symlink +src/content/* !symlink -# Treat directories as regular even if symlinked +# Treat these directories as regular directories even if they're symlinks public/blog/configs/ -symlink public/blog/images/ -symlink public/blog/infrastructure/ -symlink @@ -10,5 +12,24 @@ src/content/projects/ -symlink src/content/configurations/ -symlink src/content/external-posts/ -symlink -# Text files +# Set text files to automatically normalize line endings * text=auto + +# Markdown files +*.md text +*.mdx text + +# Source code +*.ts text +*.js text +*.json text +*.astro text +*.css text +*.html text + +# Images should be treated as binary +*.png binary +*.jpg binary +*.gif binary +*.ico binary +*.svg text diff --git a/.gitignore b/.gitignore index 82aecbf..07ab481 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,27 @@ -node_modules/ -.env -*.log +# build output dist/ .output/ -.cache/ + +# dependencies +node_modules/ + +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# environment variables +.env +.env.production + +# macOS-specific files +.DS_Store + +# Local development +.vscode/ +*.local + +# Obsidian files +.obsidian/ +node_modules diff --git a/SETUP.md b/SETUP.md new file mode 100644 index 0000000..ff636ca --- /dev/null +++ b/SETUP.md @@ -0,0 +1,43 @@ +# Automated Git Hooks Setup + +## Quick Start +```bash +# Clone and initialize the blog repository +git clone https://git.argobox.com/KeyArgo/laforceit-blog.git +cd laforceit-blog +./scripts/init-blog-repo.sh +``` + +## What This Does + +The initialization script (`init-blog-repo.sh`) automatically: +1. Configures Git to handle symbolic links properly +2. Creates all necessary directories +3. Sets up symbolic links to your Obsidian content +4. Installs Git hooks that handle content conversion +5. Makes all scripts executable + +## How Content Syncing Works + +1. **Writing Content** + - Edit content normally in Obsidian + - Changes appear instantly in the blog repository through symbolic links + +2. **Committing Changes** + - The pre-commit hook automatically converts symbolic links to real content + - Git commits the actual content + - The post-commit hook restores symbolic links automatically + +3. **No Manual Steps Required** + - All conversions happen automatically + - No need to remember any special commands + - Works the same way for all contributors + +## Troubleshooting + +If commits seem to hang: +1. Check that `core.symlinks` is enabled: `git config core.symlinks` +2. Verify symbolic links are correct: `ls -la src/content/ public/blog/` +3. Run `./scripts/init-blog-repo.sh` to reset the setup + +The initialization script can be run multiple times safely - it will fix any broken symbolic links or missing configuration. diff --git a/astro.config.mjs b/astro.config.mjs new file mode 100644 index 0000000..ab6552d --- /dev/null +++ b/astro.config.mjs @@ -0,0 +1,26 @@ +// @ts-check +import { defineConfig } from 'astro/config'; +import mdx from '@astrojs/mdx'; +import sitemap from '@astrojs/sitemap'; +import tailwind from '@astrojs/tailwind'; +// import cloudflare from '@astrojs/cloudflare'; // Commented out for local development + +// https://astro.build/config +export default defineConfig({ + site: 'https://laforceit.blog', + output: 'static', + // adapter: cloudflare(), // Commented out for local development + integrations: [ + mdx(), + sitemap(), + tailwind(), + ], + markdown: { + shikiConfig: { + theme: 'dracula', + wrap: true + }, + remarkPlugins: [], + rehypePlugins: [] + } +}); \ No newline at end of file diff --git a/astro_files.txt b/astro_files.txt new file mode 100644 index 0000000..721051a --- /dev/null +++ b/astro_files.txt @@ -0,0 +1,36 @@ + +FullName +-------- +C:\Projects\--Repo\laforceit-blog\node_modules\@astrojs\prism\Prism.astro +C:\Projects\--Repo\laforceit-blog\node_modules\astro\components\ClientRouter.astro +C:\Projects\--Repo\laforceit-blog\node_modules\astro\components\Code.astro +C:\Projects\--Repo\laforceit-blog\node_modules\astro\components\Debug.astro +C:\Projects\--Repo\laforceit-blog\node_modules\astro\components\Font.astro +C:\Projects\--Repo\laforceit-blog\node_modules\astro\components\Image.astro +C:\Projects\--Repo\laforceit-blog\node_modules\astro\components\Picture.astro +C:\Projects\--Repo\laforceit-blog\node_modules\astro\components\ResponsiveImage.astro +C:\Projects\--Repo\laforceit-blog\node_modules\astro\components\ResponsivePicture.astro +C:\Projects\--Repo\laforceit-blog\src\components\DigitalGardenGraph.astro +C:\Projects\--Repo\laforceit-blog\src\components\Footer.astro +C:\Projects\--Repo\laforceit-blog\src\components\Header.astro +C:\Projects\--Repo\laforceit-blog\src\components\Newsletter.astro +C:\Projects\--Repo\laforceit-blog\src\components\PostCard.astro +C:\Projects\--Repo\laforceit-blog\src\layouts\BaseLayout.astro +C:\Projects\--Repo\laforceit-blog\src\layouts\BlogPost.astro +C:\Projects\--Repo\laforceit-blog\src\layouts\BlogPostLayout.astro +C:\Projects\--Repo\laforceit-blog\src\pages\configurations.astro +C:\Projects\--Repo\laforceit-blog\src\pages\index.astro +C:\Projects\--Repo\laforceit-blog\src\pages\search.astro +C:\Projects\--Repo\laforceit-blog\src\pages\stack.astro +C:\Projects\--Repo\laforceit-blog\src\pages\subscription-confirmed.astro +C:\Projects\--Repo\laforceit-blog\src\pages\unsubscribe.astro +C:\Projects\--Repo\laforceit-blog\src\pages\blog\[slug].astro +C:\Projects\--Repo\laforceit-blog\src\pages\blog\index.astro +C:\Projects\--Repo\laforceit-blog\src\pages\categories\[category].astro +C:\Projects\--Repo\laforceit-blog\src\pages\categories\index.astro +C:\Projects\--Repo\laforceit-blog\src\pages\configurations\[slug].astro +C:\Projects\--Repo\laforceit-blog\src\pages\posts\[slug].astro +C:\Projects\--Repo\laforceit-blog\src\pages\projects\[slug].astro +C:\Projects\--Repo\laforceit-blog\src\pages\tag\[tag].astro +C:\Projects\--Repo\laforceit-blog\src\pages\tags\index.astro + diff --git a/backup-20250422/BaseLayout.astro b/backup-20250422/BaseLayout.astro new file mode 100644 index 0000000..e310117 --- /dev/null +++ b/backup-20250422/BaseLayout.astro @@ -0,0 +1,112 @@ +--- +import '../styles/global.css'; +import Header from '../components/Header.astro'; +import Footer from '../components/Footer.astro'; + +interface Props { + title: string; + description?: string; +} + +const { title, description = "LaForce IT - Home Lab & DevOps Insights" } = Astro.props; +--- + + + + + + + {title} + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+
+
+
+ +
+ + + +