diff --git a/monolith/README.md b/monolith/README.md index 1e989f7..b088b33 100644 --- a/monolith/README.md +++ b/monolith/README.md @@ -1,7 +1,7 @@ # Olomana - All in One -This is the one-dockerfile version of olomana containing the stable "production" containers. -Better than going module by module but don't let that stop you. -Run everything with a simple `docker-compose down && docker system prune && docker-compose up -d` +This is the one-dockerfile version of olomana containing the stable "production" containers. +Better than going module by module but don't let that stop you. +Run everything with a simple `docker-compose down && docker system prune && docker-compose up -d` Run one thing with a simple `docker-compose up serviceName` ## Setup @@ -13,7 +13,7 @@ Run one thing with a simple `docker-compose up serviceName` ##### Files Create/Fill in the following files in a `traefik/` directory under this one using the provided templates: - `traefik.toml` -- `traefik-dynamic.toml`. +- `traefik-dynamic.toml`. The file `traefik/acme.json` will be generated on first run. Make sure it eventually gets permission code 600. You might need to create a blank file before the first run. @@ -22,7 +22,7 @@ In addition to the above files, make sure the docker socket is mounted: - `/var/run/docker.sock:/var/run/docker.sock:ro` #### References -https://doc.traefik.io/traefik/getting-started/quick-start/ +https://doc.traefik.io/traefik/getting-started/quick-start/ https://doc.traefik.io/traefik/user-guides/docker-compose/basic-example/ ### Code-Server @@ -34,12 +34,12 @@ Mount the persistant storage somewhere. - `/pwspool/software/code-server/config:/config` ##### Metadata -Re-roll hashed passwords. +Re-roll hashed passwords. ./olomana.ini:/etc/grafana/grafana.ini #### References -https://docs.linuxserver.io/images/docker-code-server/ -https://coder.com/docs/code-server/latest/install#docker -https://hub.docker.com/r/linuxserver/code-server +https://docs.linuxserver.io/images/docker-code-server/ +https://coder.com/docs/code-server/latest/install#docker +https://hub.docker.com/r/linuxserver/code-server https://github.com/coder/code-server/blob/main/docs/FAQ.md#can-i-store-my-password-hashed ### Grafana @@ -63,5 +63,9 @@ To set up the data source in grafana to point to prometheus, you would refer to #### References https://grafana.com/docs/grafana/latest/setup-grafana/installation/docker/ +### Homepage +#### Instructions +##### Build +Test build with `docker-compose build homepage`. diff --git a/monolith/docker-compose.yml b/monolith/docker-compose.yml index d5f278a..8aabe38 100644 --- a/monolith/docker-compose.yml +++ b/monolith/docker-compose.yml @@ -57,7 +57,7 @@ services: depends_on: - node_exporter - prometheus - networks: + networks: - grafana - traefik user: "1003" @@ -104,3 +104,15 @@ services: labels: - traefik.enable=false + homepage: + image: homepage + container_name: homepage + build: homepage/ + restart: unless-stopped + networks: + - traefik + labels: + - traefik.http.routers.homepage.rule=Host(`www.whitney.rip`) + - traefik.http.routers.homepage.tls=true + - traefik.http.routers.homepage.tls.certresolver=lets-encrypt + - traefik.http.services.homepage.loadbalancer.server.port=80 diff --git a/monolith/homepage/Dockerfile b/monolith/homepage/Dockerfile new file mode 100644 index 0000000..a766deb --- /dev/null +++ b/monolith/homepage/Dockerfile @@ -0,0 +1,9 @@ +FROM nginx:alpine + +COPY nginx/nginx.conf /etc/nginx/nginx.conf +COPY website /usr/share/nginx/html + +EXPOSE 80 + +CMD ["nginx", "-g", "daemon off;"] + diff --git a/monolith/homepage/nginx/nginx.conf b/monolith/homepage/nginx/nginx.conf new file mode 100644 index 0000000..f18f499 --- /dev/null +++ b/monolith/homepage/nginx/nginx.conf @@ -0,0 +1,15 @@ +events { + worker_connections 1024; +} + +http { + server { + listen 81; + server_name localhost; + + location / { + root /usr/share/nginx/html; + index index.html; + } + } +} \ No newline at end of file diff --git a/monolith/homepage/website/about.html b/monolith/homepage/website/about.html new file mode 100644 index 0000000..ebf043d --- /dev/null +++ b/monolith/homepage/website/about.html @@ -0,0 +1,47 @@ + + + + + About | PWS + + + + +
+
+ + +
+
+ +
+ +
+ + + + \ No newline at end of file diff --git a/monolith/homepage/website/index.html b/monolith/homepage/website/index.html new file mode 100644 index 0000000..98e37a3 --- /dev/null +++ b/monolith/homepage/website/index.html @@ -0,0 +1,50 @@ + + + + + PWS | Pinner Web Services + + + + + +
+
+ + +
+
+ +
+
+

PWS | Pinner Web Services

+

Experience the ultimate web service tailored just for you.

+ Learn More +
+
+ +
+
+

Quote of the Day

+
+ +
+
+
+ + + + \ No newline at end of file diff --git a/monolith/homepage/website/script.js b/monolith/homepage/website/script.js new file mode 100644 index 0000000..86ecfc8 --- /dev/null +++ b/monolith/homepage/website/script.js @@ -0,0 +1,81 @@ +const quotes = [ + { + text: "The only way to do great work is to love what you do.", + author: "Steve Jobs", + link: "https://en.wikipedia.org/wiki/Steve_Jobs" + }, + { + text: "Success is not final, failure is not fatal: It is the courage to continue that counts.", + author: "Winston Churchill", + link: "https://en.wikipedia.org/wiki/Winston_Churchill" + }, + { + text: "In the end, it's not the years in your life that count. It's the life in your years.", + author: "Abraham Lincoln", + link: "https://en.wikipedia.org/wiki/Abraham_Lincoln" + }, + { + text: "Don't believe everything you read on the internet.", + author: "Abraham Lincoln", + link: "https://www.goodreads.com/quotes/4472530-the-problem-with-internet-quotes-is-that-you-cannot-always" + }, + { + text: "I should be on in a few minutes.", + author: "Jake, in the moments before baiting", + link: "https://www.youtube.com/channel/UCZctf3QSXXk9a5KzrAJ2bmw" + }, + { + text: "It's good news!", + author: "Sujay", + link: "https://anditsgood.news/" + }, + { + text: "It's bad news.", + author: "Sujay", + link: "https://anditsgood.news/" + }, + { + text: "Meow", + author: "Tobee", + link: "https://gallery.whitney.rip/library/albums/as3wif72i18kzs9q/tobee-and-maymay" + }, + { + text: "Meow", + author: "MayMay", + link: "https://gallery.whitney.rip/library/albums/as3wif72i18kzs9q/tobee-and-maymay" + }, + { + text: "It's your internet. Take it back.", + author: "DWS", + link: "https://dws.rip" + }, +]; +const failureMessageQOTD = 'Failed to fetch the quote of the day. Please try again later.'; + +async function getQOTD() { + var daysSinceEpoch = new Date().getTime() / (1000 * 60 * 60 * 24); + const idx = Math.floor(daysSinceEpoch % quotes.length); + return quotes[idx]; +} + +async function renderQOTD() { + const quoteData = await getQOTD(); + const quoteElement = document.getElementById('quote-content'); + + console.log(`Rendering Today's Quote: "${quoteData.text}" - ${quoteData.author}`); + + try { + if(quoteData) { + const html = `

"${quoteData.text}" - ${quoteData.author}

`; + quoteElement.innerHTML = html; + } else { + quoteSection.innerHTML = `

${failureMessageQOTD}

`; + } + } catch (error) { + console.error('Error rendering Quote of the Day:', error); + quoteSection.innerHTML = `

${failureMessageQOTD}

`; + } +} + +console.log("Thanks for checking out PWS!"); +document.addEventListener('DOMContentLoaded', renderQOTD); diff --git a/monolith/homepage/website/services.html b/monolith/homepage/website/services.html new file mode 100644 index 0000000..5b15243 --- /dev/null +++ b/monolith/homepage/website/services.html @@ -0,0 +1,105 @@ + + + + + Services | PWS + + + + +
+
+ + +
+
+ +
+
+

PWS Services

+

Check out some of the PWS services!

+
+
+ +
+
+
+ Gitea +
+

Gitea Private

+

I usually host code on Github, but for personal projects or my own IP, I self host. Some repos are mirrored to Github.

+
+
+
+ Code Server +
+

Code Server Private

+

Personal notebook hosting stuff like my grocery list and anything I need to keep track of in the moment. UI is not too bad on both mobile and on desktop.

+
+
+
+ Covid Tracker +
+

Covid Tracker Public

+

This was a coding project that my dad and I worked on during covid. He wanted to do some data analysis to fact check what was reported on about the covid rates. I wanted some practice with hosting web applications on PWS v1, and hosted the covid tracker website for him on PWS.

+

The website renders various charts, tables, and dashboards by interest. It additionally has a few "Checker" utilities to compare cases across cities and availability within hospitals.

+

Unfortunately, as of 2024, the US government website we scraped data for has stopped sharing information, and unfortunately this marks the end for this project. However, we still run it on PWS with the most recent batch of data.

+

Some stretch goals for this project include caching with Nginx, or converting it to a different framework like Observable.

+
+
+
+ Photoprism +
+

Photoprism Public

+

I host a personal photo gallery of memories that I'd like to remember. Photoprism makes a great open source(!) solution for doing this that is better than most other comparable projects. Its features list is rather long, and can give you a pretty decent Google Photos impression.

+
+
+
+ Websites +
+

Websites Public

+

There are a few one-of websites that I host off of PWS. One is my Recipes Website, a ad-less, bloat-less recipes website that actually tells you how to cook something instead of trying to sell you on a cookbook or something. This was written around the time that ChatGPT was becoming a household name, and this was a great project to start to learn some of the capabilities on.

+

Some other sites include my personal website (where I blog on some of these projects), and, of course, this PWS website!

+
+
+
+ Plex +
+

Plex Private

+

I have a few YouTube channels whose original video files I like to keep an archive of. It's perfectly fine to just host the files and play them in a media player, but self-hosting Plex allows me to slap on a UI for essentially free.

+
+
+
+ Discord Bots +
+

Discord Bots Public

+

At one point, when creating discord servers for special interest groups I was a part of, I found that moderation and automation were a problem with the default discord server owner experience.

+

I tried using a paid discord bot to solve some of these problems, and eventually liked it enough to purchase a lifetime subscription. However, that bot's owners started to lock features away under additional tiers and I became unhappy.

+

Just unhappy enought to sit down and learn how to use the Discord Api. With the help of the Discord API for Python, and ChatGPT by my side, I have started a repository containing some of the bots and features I have written for them. It's a nice, fun way to add functionality to a service that some of my friends choose to congregate on.

+
+
+
+ Minecraft +
+

Minecraft Private

+

Every few winters, people get stuck inside due to rain or snow and want to play some games. In the past, PWS has hosted a minecraft server to scratch that itch. Third party plugins like Dynmap allowed us to elevate the experience by hosting a live-updating server map, which is where the screenshot comes from.

+
+
+
+
+ + + + diff --git a/monolith/homepage/website/static/about/mount-olomana.jpg b/monolith/homepage/website/static/about/mount-olomana.jpg new file mode 100644 index 0000000..63db5e6 Binary files /dev/null and b/monolith/homepage/website/static/about/mount-olomana.jpg differ diff --git a/monolith/homepage/website/static/about/olomana.jpg b/monolith/homepage/website/static/about/olomana.jpg new file mode 100644 index 0000000..1772ab8 Binary files /dev/null and b/monolith/homepage/website/static/about/olomana.jpg differ diff --git a/monolith/homepage/website/static/about/whitney.jpg b/monolith/homepage/website/static/about/whitney.jpg new file mode 100644 index 0000000..4e8d60f Binary files /dev/null and b/monolith/homepage/website/static/about/whitney.jpg differ diff --git a/monolith/homepage/website/static/favicon.ico b/monolith/homepage/website/static/favicon.ico new file mode 100644 index 0000000..095b5d6 Binary files /dev/null and b/monolith/homepage/website/static/favicon.ico differ diff --git a/monolith/homepage/website/static/services/code-server.png b/monolith/homepage/website/static/services/code-server.png new file mode 100644 index 0000000..2bf1ac3 Binary files /dev/null and b/monolith/homepage/website/static/services/code-server.png differ diff --git a/monolith/homepage/website/static/services/covid-tracker.png b/monolith/homepage/website/static/services/covid-tracker.png new file mode 100644 index 0000000..1b164a7 Binary files /dev/null and b/monolith/homepage/website/static/services/covid-tracker.png differ diff --git a/monolith/homepage/website/static/services/discord.png b/monolith/homepage/website/static/services/discord.png new file mode 100644 index 0000000..f263f64 Binary files /dev/null and b/monolith/homepage/website/static/services/discord.png differ diff --git a/monolith/homepage/website/static/services/gitea.png b/monolith/homepage/website/static/services/gitea.png new file mode 100644 index 0000000..7017c35 Binary files /dev/null and b/monolith/homepage/website/static/services/gitea.png differ diff --git a/monolith/homepage/website/static/services/minecraft.png b/monolith/homepage/website/static/services/minecraft.png new file mode 100644 index 0000000..a31fa4e Binary files /dev/null and b/monolith/homepage/website/static/services/minecraft.png differ diff --git a/monolith/homepage/website/static/services/photoprism.png b/monolith/homepage/website/static/services/photoprism.png new file mode 100644 index 0000000..91b9216 Binary files /dev/null and b/monolith/homepage/website/static/services/photoprism.png differ diff --git a/monolith/homepage/website/static/services/plex.png b/monolith/homepage/website/static/services/plex.png new file mode 100644 index 0000000..9ed4599 Binary files /dev/null and b/monolith/homepage/website/static/services/plex.png differ diff --git a/monolith/homepage/website/static/services/recipes.png b/monolith/homepage/website/static/services/recipes.png new file mode 100644 index 0000000..24b872a Binary files /dev/null and b/monolith/homepage/website/static/services/recipes.png differ diff --git a/monolith/homepage/website/styles.css b/monolith/homepage/website/styles.css new file mode 100644 index 0000000..18a275d --- /dev/null +++ b/monolith/homepage/website/styles.css @@ -0,0 +1,178 @@ +body { + height: 100%; + font-family: 'Roboto', sans-serif; + margin: 0; + padding-bottom: 5%; + color: #333333; + line-height: 1.6; +} + +.container { + width: 80%; + margin: 0 auto; +} + +.container-with-footer-padding { + width: 80%; + margin: 0 auto; + padding-bottom: 60px; +} + +header { + background-color: #333333; + color: #FFFFFF; + padding: 20px 0; +} + +header .container { + display: flex; + justify-content: space-between; + align-items: center; +} + +header .logo { + font-family: 'Montserrat', sans-serif; + font-size: 1.5em; + font-weight: 600; + display: flex; + align-items: center; +} + +header nav ul { + list-style: none; + display: flex; + gap: 20px; +} + +header nav ul li { + display: inline; +} + +header nav ul li a { + color: #FFFFFF; + text-decoration: none; + font-weight: 500; +} + +.blog-image { + width: 50%; + height: auto; + border: 2px solid black; + border-radius: 5px; +} + +.nav-button { + display: inline-block; + padding: 10px 20px; + background-color: #F5844C; + color: #240f0f; + text-decoration: none; + font-weight: 600; + border-radius: 5px; + transition: background-color 0.3s ease; +} + +.service-entry { + padding-bottom: 60px; +} + +.service-public-status { + display: inline; + padding: 10px 20px; + background-color: #1daa0a; + color: #240f0f; + text-decoration: none; + font-weight: 600; + border-radius: 5px; + transition: background-color 0.3s ease; +} + +.service-private-status { + display: inline; + padding: 10px 20px; + background-color: #c72424; + color: #240f0f; + text-decoration: none; + font-weight: 600; + border-radius: 5px; + transition: background-color 0.3s ease; +} + +.nav-button:hover { + background-color: #cf5416; +} + +.hero { + background: #f4f4f4; + text-align: center; + padding: 60px 0; +} + +.hero h1 { + font-family: 'Montserrat', sans-serif; + font-size: 2.5em; + margin: 0; +} + +.hero p { + font-size: 1.2em; + margin: 20px 0; +} + +.sub-section { + background: #f4f4f4; + text-align: center; + padding: 60px 0; + padding-bottom: 60px; +} + +.sub-section h1 { + font-family: 'Montserrat', sans-serif; + font-size: 2.5em; + margin: 0; +} + +.sub-section p { + font-size: 1.2em; + margin: 20px 0; +} + +.cta-button { + display: inline-block; + padding: 10px 20px; + background-color: #F5844C; + color: #333333; + text-decoration: none; + font-weight: 600; + border-radius: 5px; + transition: background-color 0.3s ease; +} + +.cta-button:hover { + background-color: #e0a806; +} + +footer { + position: fixed; + bottom: 0; + width: 100%; + height: 5%; + background: #333333; + color: #ffffff; + text-align: center; + padding: 20px 0; +} + +footer .social-media a { + color: #ffffff; + text-decoration: none; + margin: 0 10px; +} + +footer .social-media a:hover { + text-decoration: underline; +} + +footer p { + margin: 0; +}