Initial commit: Active Directory homelab, audit documentation, verified portfolio site files, all evidence as of 2026-10-03.

This commit is contained in:
Keith Casko
2026-10-03 08:00:38 -04:00
commit 748f6d7bf9
22 changed files with 3209 additions and 0 deletions
+107
View File
@@ -0,0 +1,107 @@
# Keith Casko — Portfolio
A static personal portfolio for Keith Casko, targeting IT Support, Help Desk,
Desktop Support, Junior SysAdmin, and Cloud Support / Operations roles.
Stack: plain HTML, CSS, and a tiny vanilla JS file (mobile nav + footer year).
No build step. No frameworks.
## Run locally
Any static server works. Easiest options from the project root:
# Python 3
python -m http.server 8080
# Node (if installed)
npx serve .
Then open http://localhost:8080
Opening `index.html` directly in a browser also works; using a local server
is only needed if you later add fetches or routing.
## Project structure
keith-portfolio/
├── index.html
├── css/
│ └── styles.css
├── js/
│ └── main.js
├── assets/
│ ├── images/ # portrait, hero rack/workstation photos
│ ├── screenshots/ # project screenshots
│ └── resume/ # keith-casko-resume.pdf
└── README.md
## Things to replace before publishing
Every spot that needs a real value is marked with `REPLACE` in an HTML
comment. Search the project for `REPLACE` to find all of them. The main ones:
- **Resume PDF** — put the file at `assets/resume/keith-casko-resume.pdf`
(two links in `index.html`: hero "Download Resume" button and footer).
- **GitHub** — footer link, replace `https://github.com/REPLACE_ME`.
- **LinkedIn** — footer link, replace `https://www.linkedin.com/in/REPLACE_ME`.
- **Email** — footer and Contact section, replace `you@example.com`
(two `mailto:` links).
- **Project links** — four `View Project ›` links in the Featured Projects
section currently point to `#`. Point each to the real repo or live demo.
## Screenshots & images
Drop the real files into these paths and remove the placeholder `<div>`s
in `index.html` (replace with `<img src="…" alt="…">`):
- `assets/images/hero-rack.jpg` — homelab, rack, or workstation photo
- `assets/images/portrait.jpg` — portrait photo for the About section
- `assets/screenshots/bytegeist-ad.jpg` — Windows Server / AD lab screenshot
- `assets/screenshots/bytegeist-support.jpg` — Support Lab app screenshot
- `assets/screenshots/linux-docker.jpg` — Grafana / Portainer / Uptime Kuma
- `assets/screenshots/aws-tracker.jpg` — AWS Cloud Study Tracker UI
Keep images reasonably sized (e.g. 1600px wide max, JPEG quality ~80, or
WebP) for fast loads.
## Deploy
### AWS Amplify (manual deploy, no Git connection required)
1. In the Amplify Console, choose **Host web app → Deploy without Git**.
2. Zip the whole project folder (`index.html`, `css/`, `js/`, `assets/`)
and drag the zip into the uploader. Name the environment e.g. `prod`.
3. Amplify gives you an `*.amplifyapp.com` URL. To use a custom domain,
open the app → **Domain management → Add domain**.
For redeploys, upload a new zip to the same environment.
### GitHub Pages
1. Push this folder to a GitHub repo (e.g. `keith-portfolio`).
2. Repo → **Settings → Pages**.
3. Source: **Deploy from a branch**. Branch: `main` (or `master`),
folder: `/ (root)`. Save.
4. GitHub publishes to `https://<username>.github.io/keith-portfolio/`.
Allow a minute for the first build.
For a custom domain, add a `CNAME` file at the project root containing
the domain, and configure DNS to point at GitHub Pages.
### Vercel
1. Install the CLI once: `npm i -g vercel`.
2. From the project root: `vercel` (follow prompts) and then `vercel --prod`.
Or connect the GitHub repo in the Vercel dashboard — framework preset is
**Other**; no build command; output directory is `.` (the repo root).
## Accessibility & performance notes
- Semantic HTML (`<header>`, `<nav>`, `<main>`, `<section>`, `<article>`,
`<footer>`), one `<h1>`, proper heading hierarchy.
- Visible focus outlines on links and buttons.
- Mobile nav toggle, responsive layouts at 980px and 640px.
- No external JS/CSS dependencies — single CSS file, single JS file.
- `alt` text / `aria-label`s on image placeholders; update them when
swapping placeholders for real images.
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

+67
View File
@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 980 620" font-family="Segoe UI, Arial, sans-serif" font-size="13" fill="#2b3540">
<defs>
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M0,0 L10,5 L0,10 z" fill="#1a6fa5"/>
</marker>
<style>
.title { font-family: Georgia, serif; font-size: 20px; fill: #0b1d2e; }
.caption { font-size: 11px; fill: #556372; }
.box { fill: #ffffff; stroke: #1a6fa5; stroke-width: 2; }
.box-dc { fill: #f3f5f8; stroke: #0b1d2e; stroke-width: 2; }
.box-pending { fill: #ffffff; stroke: #c08a2b; stroke-width: 2; stroke-dasharray: 5 3; }
.box-net { fill: #ffffff; stroke: #d0d7df; stroke-width: 1; stroke-dasharray: 4 3; }
.hdr { font-weight: bold; fill: #0b1d2e; }
.role { font-size: 11px; fill: #556372; }
.link { stroke: #1a6fa5; stroke-width: 1.5; fill: none; }
.net-label { font-size: 12px; fill: #155a86; font-weight: bold; }
.pending-tag { font-size: 10px; fill: #c08a2b; font-weight: bold; }
</style>
</defs>
<text x="490" y="34" class="title" text-anchor="middle">ByteGeist Active Directory Homelab — ad.bytegeist.lab</text>
<text x="490" y="52" class="caption" text-anchor="middle">VMware Workstation Pro 17 · Windows 11 Pro for Workstations host · verified 2026-10-03</text>
<line x1="60" y1="64" x2="920" y2="64" stroke="#1a6fa5" stroke-width="2"/>
<line x1="60" y1="68" x2="920" y2="68" stroke="#d0d7df" stroke-width="1"/>
<rect x="400" y="90" width="180" height="46" class="box"/>
<text x="490" y="110" class="hdr" text-anchor="middle">Host &amp; Internet</text>
<text x="490" y="126" class="role" text-anchor="middle">VMware NAT · host 192.168.31.1</text>
<rect x="60" y="170" width="860" height="150" class="box-net"/>
<text x="78" y="190" class="net-label">VMnet8 — NAT · 192.168.31.0/24</text>
<rect x="110" y="210" width="200" height="90" class="box-dc"/>
<text x="210" y="232" class="hdr" text-anchor="middle">DC01</text>
<text x="210" y="250" class="role" text-anchor="middle">Windows Server 2022 Std</text>
<text x="210" y="268" class="role" text-anchor="middle">AD DS · DNS · GC · PDC</text>
<text x="210" y="286" class="role" text-anchor="middle">192.168.31.10</text>
<rect x="340" y="210" width="200" height="90" class="box"/>
<text x="440" y="232" class="hdr" text-anchor="middle">FILE01</text>
<text x="440" y="250" class="role" text-anchor="middle">Windows Server 2022 Std</text>
<text x="440" y="268" class="role" text-anchor="middle">SMB · share: IT (RBAC)</text>
<text x="440" y="286" class="role" text-anchor="middle">192.168.31.20</text>
<rect x="620" y="210" width="240" height="90" class="box"/>
<text x="740" y="232" class="hdr" text-anchor="middle">OPNsense (FreeBSD)</text>
<text x="740" y="250" class="role" text-anchor="middle">WAN · VMnet8 (DHCP)</text>
<text x="740" y="268" class="role" text-anchor="middle">LAN · VMnet2 (192.168.254.1)</text>
<text x="740" y="286" class="role" text-anchor="middle">Firewall / router (lab)</text>
<line class="link" x1="490" y1="136" x2="490" y2="168" marker-end="url(#arrow)"/>
<rect x="60" y="400" width="860" height="150" class="box-net"/>
<text x="78" y="420" class="net-label">VMnet2 — host-only · 192.168.254.0/24 · behind OPNsense LAN</text>
<line class="link" x1="740" y1="300" x2="740" y2="398" marker-end="url(#arrow)"/>
<rect x="380" y="440" width="220" height="90" class="box-pending"/>
<text x="490" y="462" class="hdr" text-anchor="middle">WIN11-01</text>
<text x="490" y="480" class="role" text-anchor="middle">Windows 11 Education</text>
<text x="490" y="498" class="role" text-anchor="middle">Domain-joined (ad.bytegeist.lab)</text>
<text x="490" y="516" class="pending-tag" text-anchor="middle">NIC currently bridged → fix in VMware</text>
<text x="60" y="590" class="caption">Domain: ad.bytegeist.lab · NetBIOS: BGLAB · Forest/Domain mode: Windows2016 · GC &amp; PDC on DC01 · PDC time → time.windows.com</text>
<text x="60" y="606" class="caption">OUs: ByteGeist/{Servers, Workstations, Groups, Users/{HR, IT, Sales}} · 7 lab users · 7 department groups · diagram reflects verified ipconfig + Get-ADDomain + Get-SmbShare</text>
</svg>

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.
+4
View File
@@ -0,0 +1,4 @@
# Placeholders for screenshots
Replace with real project screenshots. See ../../README.md for the expected
filenames and locations.
Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 530 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 370 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 593 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 530 KiB

+702
View File
@@ -0,0 +1,702 @@
/* Keith Casko — Portfolio
Design: enterprise IT / infrastructure (late-2000s–early-2010s refined)
Palette: navy, steel blue, white, light gray, charcoal
*/
/* ---------- Reset & base ---------- */
*,
*::before,
*::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
:root {
--navy: #0b1d2e;
--navy-2: #10263d;
--steel: #1a6fa5;
--steel-dark: #155a86;
--rule: #d0d7df;
--rule-soft: #e4e8ee;
--bg: #f3f5f8;
--panel: #ffffff;
--text: #2b3540;
--muted: #566471;
--muted-2: #4b5663;
}
body {
margin: 0;
font-family: "Segoe UI", Arial, Helvetica, sans-serif;
font-size: 16px;
line-height: 1.6;
color: var(--text);
background: var(--bg);
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
}
h1, h2, h3, h4 {
font-family: Georgia, "Times New Roman", serif;
color: var(--navy-2);
font-weight: 700;
line-height: 1.25;
margin: 0 0 .55em;
letter-spacing: -0.005em;
}
p { margin: 0 0 1em; }
a { color: var(--steel); text-decoration: none; }
a:hover { text-decoration: underline; }
a:focus-visible,
button:focus-visible {
outline: 2px solid var(--steel);
outline-offset: 2px;
border-radius: 2px;
}
img { max-width: 100%; display: block; }
code {
font-family: "Consolas", "Menlo", "Courier New", monospace;
font-size: 0.92em;
background: #eef2f6;
border: 1px solid var(--rule-soft);
padding: 0 4px;
border-radius: 3px;
}
/* ---------- Layout ---------- */
.container {
width: 100%;
max-width: 1160px;
margin: 0 auto;
padding: 0 24px;
}
section { padding: 64px 0; }
.section-head {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 16px;
margin-bottom: 32px;
padding-bottom: 12px;
border-bottom: 2px solid var(--steel);
position: relative;
}
.section-head::after {
content: "";
position: absolute;
left: 0; right: 0;
bottom: -5px;
height: 1px;
background: var(--rule);
}
.section-head h2 { margin: 0; font-size: 26px; color: var(--navy-2); }
.section-head .subtitle { color: var(--muted); font-size: 14px; }
/* ---------- Header ---------- */
.site-header {
background: var(--navy);
color: #fff;
border-bottom: 4px solid var(--steel);
}
.site-header .container {
display: flex;
align-items: center;
justify-content: space-between;
gap: 24px;
padding-top: 20px;
padding-bottom: 20px;
}
.brand .name {
font-family: Georgia, "Times New Roman", serif;
font-size: 24px;
font-weight: 700;
color: #fff;
line-height: 1.1;
letter-spacing: 0.1px;
}
.brand .tagline {
display: block;
font-size: 12.5px;
color: #a9b8c7;
margin-top: 4px;
letter-spacing: .25px;
}
.brand .location {
display: inline-block;
margin-left: 10px;
padding-left: 10px;
border-left: 1px solid #3b556f;
color: #8ea1b5;
font-size: 12.5px;
}
.site-nav ul {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-wrap: wrap;
gap: 2px;
}
.site-nav a {
display: block;
padding: 8px 14px;
color: #e4ecf3;
font-size: 14px;
border-radius: 3px;
transition: background-color .12s ease, color .12s ease;
}
.site-nav a:hover { background: #16314a; text-decoration: none; color: #fff; }
.site-nav a.active {
background: var(--steel);
color: #fff;
box-shadow: inset 0 -2px 0 rgba(0,0,0,0.15);
}
.nav-toggle {
display: none;
background: transparent;
border: 1px solid #3b556f;
color: #fff;
padding: 6px 10px;
font-size: 14px;
border-radius: 3px;
cursor: pointer;
}
/* ---------- Hero ---------- */
.hero { padding: 44px 0 56px; }
.hero-grid {
background: var(--panel);
border: 1px solid var(--rule);
border-top: 3px solid var(--steel);
border-radius: 4px;
box-shadow: 0 2px 6px rgba(16, 38, 61, 0.06);
padding: 40px;
display: grid;
grid-template-columns: 1.1fr 1fr;
gap: 40px;
align-items: center;
}
.hero h1 { font-size: 34px; margin-bottom: 18px; line-height: 1.2; }
.hero p { color: var(--muted-2); font-size: 16px; }
.hero .lede { color: var(--text); }
.hero-actions {
display: flex;
flex-wrap: wrap;
gap: 12px;
margin-top: 24px;
}
.btn {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 10px 18px;
font-size: 14px;
font-weight: 600;
border-radius: 3px;
border: 1px solid transparent;
cursor: pointer;
text-decoration: none;
line-height: 1.2;
transition: background-color .12s ease, border-color .12s ease, color .12s ease;
}
.btn-primary { background: var(--steel); color: #fff; border-color: var(--steel-dark); }
.btn-primary:hover { background: var(--steel-dark); color: #fff; text-decoration: none; }
.btn-secondary { background: #fff; color: var(--navy-2); border-color: #c3cbd4; }
.btn-secondary:hover { background: #eef2f6; border-color: #9fadbd; text-decoration: none; }
.hero-image {
background: #e9edf1;
border: 1px solid var(--rule);
border-radius: 3px;
overflow: hidden;
aspect-ratio: 4 / 3;
display: flex;
align-items: center;
justify-content: center;
}
.hero-image img { width: 100%; height: 100%; object-fit: cover; }
.image-placeholder {
width: 100%;
height: 100%;
background:
repeating-linear-gradient(45deg, #e3e8ed 0, #e3e8ed 10px, #eef2f6 10px, #eef2f6 20px);
color: #5a6775;
font-size: 12.5px;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
padding: 12px;
letter-spacing: .2px;
}
/* ---------- Projects ---------- */
.projects-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20px;
}
.project-card {
background: var(--panel);
border: 1px solid var(--rule);
border-radius: 4px;
box-shadow: 0 1px 2px rgba(16, 38, 61, 0.04);
display: flex;
flex-direction: column;
overflow: hidden;
transition: border-color .15s ease, box-shadow .15s ease;
}
.project-card:hover {
border-color: #9fb6ca;
box-shadow: 0 4px 14px rgba(16, 38, 61, 0.10);
}
.project-card .thumb {
background: #e9edf1;
aspect-ratio: 16 / 10;
border-bottom: 1px solid var(--rule);
overflow: hidden;
}
.project-card .thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.project-card .thumb .image-placeholder { font-size: 12px; }
.project-card .body { padding: 18px 18px 20px; display: flex; flex-direction: column; flex: 1; }
.project-card h3 { font-size: 18px; margin-bottom: 10px; color: var(--navy-2); }
.project-card:hover h3 { color: var(--steel-dark); }
.project-card p {
font-size: 14px;
line-height: 1.55;
color: var(--muted-2);
margin-bottom: 16px;
flex: 1;
}
.project-card .view-link {
font-size: 13.5px;
font-weight: 600;
color: var(--steel);
align-self: flex-start;
}
.project-card .view-link::after { content: " \203A"; color: var(--steel); }
/* ---------- What I Work With ---------- */
.skills-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 18px;
}
.skill-card {
background: var(--panel);
border: 1px solid var(--rule);
border-radius: 4px;
padding: 18px 20px;
box-shadow: 0 1px 2px rgba(16, 38, 61, 0.04);
}
.skill-head {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 10px;
padding-bottom: 8px;
border-bottom: 1px solid var(--rule-soft);
}
.skill-head .ico { width: 22px; height: 22px; flex: 0 0 22px; color: var(--steel); }
.skill-card h3 {
font-size: 15px;
font-family: "Segoe UI", Arial, sans-serif;
color: var(--navy-2);
margin: 0;
line-height: 1.2;
}
.skill-card ul {
list-style: none;
margin: 0;
padding: 0;
font-size: 13.5px;
line-height: 1.55;
color: var(--muted-2);
}
.skill-card li { padding: 2px 0; }
/* ---------- Troubleshooting ---------- */
.notes-list {
background: var(--panel);
border: 1px solid var(--rule);
border-radius: 4px;
overflow: hidden;
box-shadow: 0 1px 2px rgba(16, 38, 61, 0.04);
}
.note-item {
display: grid;
grid-template-columns: 44px 1fr 24px;
gap: 18px;
align-items: start;
padding: 18px 22px;
border-bottom: 1px solid var(--rule-soft);
transition: background-color .12s ease;
}
.note-item:last-child { border-bottom: 0; }
.note-item:hover { background: #f7f9fb; }
.note-item .icon {
width: 36px;
height: 36px;
background: #eaf1f7;
color: var(--steel);
border: 1px solid #cfdbe6;
border-radius: 3px;
display: flex;
align-items: center;
justify-content: center;
font-weight: 700;
font-size: 11px;
font-family: "Consolas", monospace;
letter-spacing: .5px;
}
.note-item h3 {
font-family: "Segoe UI", Arial, sans-serif;
font-size: 16px;
margin: 0 0 4px;
color: var(--steel);
}
.note-item:hover h3 { color: var(--steel-dark); }
.note-item p { margin: 0; color: var(--muted-2); font-size: 14px; }
.note-item ul {
margin: 8px 0 0;
padding-left: 20px;
color: var(--muted-2);
font-size: 13.5px;
line-height: 1.6;
}
.note-item li { padding: 1px 0; }
.note-item .chevron { color: #94a1ae; font-size: 20px; padding-top: 6px; }
/* ---------- About ---------- */
.about-grid {
display: grid;
grid-template-columns: 1fr 1.4fr 1fr;
gap: 24px;
align-items: start;
}
.about-photo {
background: #e9edf1;
border: 1px solid var(--rule);
border-radius: 3px;
aspect-ratio: 1 / 1;
overflow: hidden;
}
.about-text {
background: var(--panel);
border: 1px solid var(--rule);
border-top: 3px solid var(--steel);
border-radius: 4px;
padding: 22px 24px;
}
.about-text h3 { font-size: 19px; margin-bottom: 12px; }
.pull-quote {
background: #eef2f6;
border: 1px solid var(--rule);
border-left: 3px solid var(--steel);
border-radius: 3px;
padding: 20px 22px;
font-style: italic;
color: var(--text);
font-size: 14.5px;
line-height: 1.6;
}
.pull-quote .mark {
font-family: Georgia, serif;
font-size: 34px;
color: var(--steel);
line-height: 0;
position: relative;
top: 10px;
margin-right: 4px;
}
/* ---------- Education / Experience ---------- */
.two-col {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 24px;
}
.panel {
background: var(--panel);
border: 1px solid var(--rule);
border-top: 3px solid var(--steel);
border-radius: 4px;
padding: 22px 26px;
box-shadow: 0 1px 2px rgba(16, 38, 61, 0.04);
}
.panel h3 { font-size: 18px; margin-bottom: 6px; }
.panel .meta { color: var(--muted); font-size: 13.5px; margin-bottom: 14px; }
.panel h4 {
font-family: "Segoe UI", Arial, sans-serif;
font-size: 13.5px;
color: var(--navy-2);
margin: 16px 0 6px;
text-transform: uppercase;
letter-spacing: .4px;
}
.panel ul {
margin: 0;
padding-left: 20px;
font-size: 14px;
line-height: 1.6;
color: var(--muted-2);
}
.panel li { padding: 2px 0; }
/* ---------- Contact banner ---------- */
.contact-cta {
background: var(--navy);
color: #e4ecf3;
border-radius: 4px;
border-top: 3px solid var(--steel);
padding: 28px 32px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 20px;
}
.contact-cta h2 { color: #fff; margin: 0 0 6px; font-size: 22px; }
.contact-cta p { margin: 0; color: #a9b8c7; font-size: 14.5px; }
/* ---------- Footer ---------- */
.site-footer {
background: var(--navy);
color: #a9b8c7;
padding: 24px 0;
margin-top: 48px;
border-top: 4px solid var(--steel);
font-size: 13.5px;
}
.site-footer .container {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
flex-wrap: wrap;
}
.site-footer a { color: #cfd8e1; }
.site-footer a:hover { color: #fff; }
.footer-links {
list-style: none;
margin: 0;
padding: 0;
display: flex;
gap: 20px;
flex-wrap: wrap;
}
/* ---------- Responsive ---------- */
@media (max-width: 980px) {
.hero-grid { grid-template-columns: 1fr; padding: 32px; }
.projects-grid { grid-template-columns: repeat(2, 1fr); }
.skills-grid { grid-template-columns: repeat(2, 1fr); }
.about-grid { grid-template-columns: 1fr; }
.two-col { grid-template-columns: 1fr; }
.contact-cta { flex-direction: column; align-items: flex-start; }
}
@media (max-width: 640px) {
body { font-size: 15.5px; }
section { padding: 44px 0; }
.hero { padding: 28px 0 36px; }
.hero-grid { padding: 22px; }
.hero h1 { font-size: 27px; }
.section-head h2 { font-size: 22px; }
.projects-grid { grid-template-columns: 1fr; }
.skills-grid { grid-template-columns: 1fr; }
.note-item { grid-template-columns: 36px 1fr; padding: 16px; }
.note-item .chevron { display: none; }
.brand .location { display: block; margin: 4px 0 0; padding-left: 0; border-left: 0; }
.nav-toggle { display: inline-block; }
.site-header .container { flex-wrap: wrap; }
.site-nav { flex-basis: 100%; display: none; }
.site-nav.open { display: block; }
.site-nav ul { flex-direction: column; gap: 2px; }
.site-nav a { padding: 10px 12px; }
.section-head { flex-direction: column; align-items: flex-start; gap: 4px; }
}
.about-headshot {
width: 100%;
height: 100%;
object-fit: cover;
object-position: center 20%;
display: block;
}
.contact-actions {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
/* ---------- Diagram-style project thumb ---------- */
.project-card .thumb-diagram {
background: #ffffff;
display: flex;
align-items: center;
justify-content: center;
padding: 10px;
}
.project-card .thumb-diagram img { width: 100%; height: 100%; object-fit: contain; }
.project-card .card-link { display: block; color: inherit; }
.project-card .card-link:hover { text-decoration: none; }
/* ---------- Homelab detail page ---------- */
.eyebrow { font-size: 13px; color: var(--muted); margin: 0 0 10px; }
.eyebrow a { color: var(--steel); font-weight: 600; }
.lab-hero {
background: var(--panel);
border: 1px solid var(--rule);
border-top: 3px solid var(--steel);
border-radius: 4px;
box-shadow: 0 2px 6px rgba(16, 38, 61, 0.06);
padding: 32px 36px;
display: grid;
grid-template-columns: 1fr 1.1fr;
gap: 32px;
align-items: center;
}
.lab-hero h1 { font-size: 30px; margin-bottom: 14px; }
.lab-hero .lede { color: var(--text); }
.lab-hero-figure { margin: 0; }
.lab-hero-figure img {
width: 100%;
border: 1px solid var(--rule);
border-radius: 3px;
background: #fff;
}
.lab-hero-figure figcaption {
font-size: 12px;
color: var(--muted);
padding: 8px 2px 0;
line-height: 1.5;
}
.lab-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 18px; }
.lab-tags span {
background: #eef2f6;
border: 1px solid var(--rule);
color: var(--navy-2);
padding: 4px 10px;
font-size: 12px;
border-radius: 3px;
font-weight: 600;
letter-spacing: .2px;
}
.lab-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
.lab-panel {
background: var(--panel);
border: 1px solid var(--rule);
border-top: 3px solid var(--steel);
border-radius: 4px;
padding: 22px 26px;
box-shadow: 0 1px 2px rgba(16, 38, 61, 0.04);
}
.lab-panel h3 { font-size: 17px; margin: 0 0 10px; }
.lab-panel h3.h3-sub { font-size: 15px; margin-top: 18px; }
.lab-panel h4 {
font-family: "Segoe UI", Arial, sans-serif;
font-size: 12.5px;
color: var(--navy-2);
margin: 14px 0 6px;
text-transform: uppercase;
letter-spacing: .4px;
}
.kv { list-style: none; margin: 0; padding: 0; font-size: 14px; }
.kv li {
display: grid;
grid-template-columns: 150px 1fr;
gap: 10px;
padding: 6px 0;
border-bottom: 1px solid var(--rule-soft);
}
.kv li:last-child { border-bottom: 0; }
.kv li span { color: var(--muted); font-size: 13px; }
.lab-tree, .lab-code {
background: #0b1d2e;
color: #e4ecf3;
font-family: "Consolas", "Menlo", monospace;
font-size: 12.5px;
line-height: 1.55;
padding: 14px 16px;
border-radius: 3px;
overflow-x: auto;
margin: 0 0 10px;
white-space: pre;
}
.lab-code { color: #b8d6ea; }
.mono-list { font-family: "Consolas", "Menlo", monospace; font-size: 13px; color: var(--text); margin: 6px 0 0; }
.lab-table-wrap { overflow-x: auto; }
.lab-table {
width: 100%;
border-collapse: collapse;
background: var(--panel);
border: 1px solid var(--rule);
font-size: 14px;
}
.lab-table thead th {
text-align: left;
background: #eef2f6;
color: var(--navy-2);
padding: 10px 12px;
border-bottom: 1px solid var(--rule);
font-size: 13px;
font-family: "Segoe UI", Arial, sans-serif;
}
.lab-table td {
padding: 10px 12px;
border-bottom: 1px solid var(--rule-soft);
vertical-align: top;
}
.lab-table tr:last-child td { border-bottom: 0; }
.lab-table-sm { font-size: 13px; }
.lab-table-sm th, .lab-table-sm td { padding: 7px 10px; }
.status-ok {
background: #eaf5ec;
border-left: 3px solid #3f8c53;
color: #26492f;
padding: 8px 12px;
margin: 10px 0 0;
font-size: 13.5px;
border-radius: 2px;
}
.lab-skill-list {
background: var(--panel);
border: 1px solid var(--rule);
border-radius: 4px;
padding: 20px 28px 20px 44px;
list-style: disc;
color: var(--muted-2);
font-size: 14.5px;
line-height: 1.65;
}
.lab-skill-list li { padding: 3px 0; }
.lab-skill-list strong { color: var(--navy-2); }
@media (max-width: 980px) {
.lab-hero { grid-template-columns: 1fr; padding: 24px; }
.lab-grid-2 { grid-template-columns: 1fr; }
}
@media (max-width: 640px) {
.lab-hero h1 { font-size: 24px; }
.lab-panel { padding: 18px; }
.lab-tree, .lab-code { font-size: 12px; padding: 12px; }
}
+131
View File
@@ -0,0 +1,131 @@
# ByteGeist Active Directory Homelab — audit log
**Last run:** 2026-10-03 03:09 ET
**Operator:** Keith Casko
**Host:** `BYTEGEIST` (Windows 11 Pro for Workstations, 64 GB RAM)
**Hypervisor:** VMware Workstation Pro 17
**Transcripts:** `D:\Repos\ad-lab\transcripts\`
---
## Phase 1 — Discovery
| VM | Guest OS | vCPU | RAM | NIC → VMnet | VMX |
|---|---|---|---|---|---|
| DC01 | Server 2022 Std | 2 | 4 GB | VMnet8 (NAT) | `D:\Homelab\DC01\Windows Server 2022.vmx` |
| FILE01 | Server 2022 Std | 4 | 4 GB | VMnet8 (NAT) | `D:\Homelab\FILE01\FILE01.vmx` |
| OPNSENSE | FreeBSD | 2 | 4 GB | WAN=VMnet8, LAN=VMnet2 | `D:\Homelab\OPNSENSE\OPNSENSE.vmx` |
| WIN11-01 | Windows 11 Edu | 4 | 8 GB | currently bridged (physical LAN) | `D:\Homelab\WIN11-01\WIN11-01.vmx` (encrypted) |
Virtual networks (from `vmnetdhcp.conf` + host `ipconfig`):
| Network | Type | Subnet | Host IP | Role |
|---|---|---|---|---|
| VMnet8 | NAT | 192.168.31.0/24 | 192.168.31.1 | Lab "uplink" — DC01, FILE01, OPNsense WAN |
| VMnet2 | Host-only | 192.168.254.0/24 | 192.168.254.1 | OPNsense LAN segment |
| VMnet1 | Host-only | 192.168.229.0/24 | 192.168.229.1 | Unused |
## Phase 3 — DC01 (verified)
- Hostname `DC01`, Server 2022 Std, IPv4 `192.168.31.10/24`.
- Domain `ad.bytegeist.lab`, NetBIOS `BGLAB`, Domain/Forest mode `Windows2016`.
- DC01 holds **PDCEmulator, SchemaMaster, DomainNamingMaster, GC**.
- Services `NTDS, DNS, Netlogon, KDC, W32Time, DFSR` — all Running.
- `SYSVOL` → `C:\Windows\SYSVOL\sysvol`, `NETLOGON` → `…\SCRIPTS`.
- DNS zones (AD-integrated): `ad.bytegeist.lab`, `_msdcs.ad.bytegeist.lab`, three default reverse zones.
- `dcdiag /q`: silent (clean after Phase 7 fixes).
- `repadmin /replsummary`: no deltas, no errors — single DC, expected.
### OU structure (verified)
```
ad.bytegeist.lab/
├── ByteGeist/
│ ├── Groups
│ ├── Servers
│ ├── Workstations
│ └── Users/{HR, IT, Sales}
└── Domain Controllers
```
### Users (verified; lab accounts, no PII)
Administrator, Guest (disabled), krbtgt (disabled, system), keith — in `CN=Users`
`OU=HR`: jwilson, ldavis
`OU=IT`: bsmith, kcasko, sjohnson
`OU=Sales`: mbrown, tmiller
### Lab-created groups (all Global/Security, under `OU=Groups,OU=ByteGeist`)
Accounting, Help Desk, HR Employees, IT Employees, Management, Sales Employees, VPN Users.
### Computers in AD
| Name | OS | Last logon |
|---|---|---|
| DC01 | Server 2022 | 2026-10-03 02:35 |
| FILE01 | Server 2022 | 2026-10-03 02:36 |
| WIN11-01 | Windows 11 Education | 2026-08-05 14:46 |
## Phase 4 — FILE01 (verified)
- Hostname `FILE01`, Server 2022 Std, IPv4 `192.168.31.20/24`.
- Domain-joined to `ad.bytegeist.lab` (`DomainRole 3` = member server).
- `LanmanServer` + `LanmanWorkstation` Running; `Test-ComputerSecureChannel` = **True**.
- Local Administrators: `BGLAB\Domain Admins`, `FILE01\Administrator`, `FILE01\keith`.
**Share: `IT` → `C:\Shares\IT`**
Share-level permissions (`Get-SmbShareAccess`):
| Account | AccessControlType | Rights |
|---|---|---|
| BGLAB\Domain Admins | Allow | Full |
| BGLAB\IT Employees | Allow | Change |
NTFS ACL on `C:\Shares\IT` (`Get-Acl`):
| Identity | Rights | Inherited |
|---|---|---|
| BGLAB\IT Employees | Modify, Synchronize | False (explicit) |
| NT AUTHORITY\SYSTEM | FullControl | True |
| BUILTIN\Administrators | FullControl | True |
| BUILTIN\Users | ReadAndExecute + AppendData + CreateFiles | True |
| CREATOR OWNER | Full on child objects | True |
Only one share is currently published. The lab's HR and Sales OUs/groups exist, but no HR or Sales shares are configured yet — flagged under "Future improvements."
## Phase 5 — WIN11-01 (access pending)
Not audited live. Two independent blockers:
1. **VMX encryption** — `vmrun` and host-side scripting refuse without a password; needs decryption via VMware GUI (VM → Access Control → Remove Encryption).
2. **NIC bridged to physical LAN** — WIN11-01 reports `192.168.1.132` with gateway `192.168.1.1` and DNS `192.168.1.1`. It has no route to DC01 (`192.168.31.10` on VMnet8). `Test-NetConnection 192.168.31.10 -Port 53` timed out, `Resolve-DnsName ad.bytegeist.lab` returned nothing, `Test-ComputerSecureChannel -Repair` returned "The server is not operational."
AD-side evidence that the join still exists: `Get-ADComputer WIN11-01` shows the account enabled, OS Windows 11 Education, last successful domain logon 2026-08-05 — before the NIC change.
Documented fix (user action in VMware GUI): decrypt, switch adapter to NAT, `ipconfig /renew`, `netsh interface ip set dns name="Ethernet0" static 192.168.31.10 primary`, `Test-ComputerSecureChannel -Repair`.
## Phase 6 — Network validation
- DC01 ↔ FILE01: both on VMnet8/192.168.31.0/24. SMB + Kerberos verified by successful `Invoke-Command FILE01` from DC01.
- DC01 → `time.windows.com`: resolves and syncs (stratum 5, source IP 168.61.215.74).
- WIN11-01 → DC01: broken (see Phase 5).
## Phase 7 — Problems found and fixed
| # | Problem | Fix | Status |
|---|---|---|---|
| 1 | PDC time source `Local CMOS Clock` (stratum 1 LOCL — would cause Kerberos skew failures as members drift) | `w32tm /config /manualpeerlist:"time.windows.com,0x9 pool.ntp.org,0x9 time.nist.gov,0x9" /syncfromflags:manual /reliable:yes /update` → PDC now stratum 5 syncing from `time.windows.com` (168.61.215.74) | **Fixed** |
| 2 | Stale `dcdiag` SystemLog failure from an unexpected shutdown on 2026-08-07 | `wevtutil cl System`; re-ran `dcdiag /q` — silent | **Fixed** |
| 3 | `bglab\keith` is a standard Domain User, couldn't WinRM into FILE01 (Access Denied) | `Add-ADGroupMember 'Domain Admins' keith` as `BGLAB\Administrator` — logged as lab maintenance | **Fixed** |
| 4 | FILE01 and DC01 on plain NAT (VMnet8), WIN11-01 on different segment — OPNsense doesn't see east-west server traffic | Documented; migration to pure VMnet2 behind OPNsense is a planned improvement | **Documented** |
| 5 | WIN11-01 NIC bridged to physical LAN, no route to DC01 | Documented; requires VMware GUI (decrypt + change adapter) | **Pending user action** |
| 6 | WIN11-01 vmx encrypted — blocks `vmrun` and automation | Documented; user to remove encryption via VMware GUI | **Pending user action** |
## Security notes
- No passwords, DSRM, krbtgt, SIDs, or recovery credentials captured in transcripts or portfolio artifacts.
- Lab is behind VMware NAT; no inbound exposure to the host network or the internet.
- Transcripts live under `D:\Repos\ad-lab\transcripts\` on the host, not on the DC.
- `keith` was elevated to `Domain Admins` **in the lab only**; this account has no production use.
+147
View File
@@ -0,0 +1,147 @@
# Windows Server / Active Directory Homelab
## Objective
Build a self-contained Windows Server 2022 Active Directory environment to practice the day-to-day tasks a Help Desk / Junior SysAdmin role actually asks for: domain join, user and group management, OU design, SMB file services, NTFS permissions, DNS, time synchronization, and the troubleshooting loop when something breaks.
Everything on this page is from the real lab on my workstation. Nothing is fabricated.
## Architecture
![ByteGeist AD homelab topology](../assets/images/homelab-topology.svg)
Three virtual machines on VMware Workstation Pro 17, plus an OPNsense firewall VM that sits between the server segment and a separate client segment. A Windows Server 2022 domain controller runs AD DS, DNS, and PDC Emulator duties for the forest; a member server runs SMB file services; a Windows 11 client is domain-joined.
## Systems
| System | OS | Role | Address | Purpose |
|---|---|---|---|---|
| DC01 | Windows Server 2022 Standard | Domain controller | 192.168.31.10 | AD DS, DNS, PDC Emulator, Schema Master, Global Catalog |
| FILE01 | Windows Server 2022 Standard | Member server | 192.168.31.20 | SMB file services |
| WIN11-01 | Windows 11 Education | Domain client | (NIC change in progress) | Domain-joined workstation |
| OPNSENSE | FreeBSD / OPNsense | Firewall / router | VMnet8 ↔ VMnet2 | Separates server and client segments |
## Active Directory
- **Forest / Domain:** `ad.bytegeist.lab`
- **NetBIOS:** `BGLAB`
- **Forest and Domain functional level:** `Windows2016`
- **FSMO roles:** all five held by `DC01.ad.bytegeist.lab`
- **Global Catalog:** DC01
Verified with `Get-ADDomain`, `Get-ADForest`, and `Get-ADDomainController`.
## DNS
AD-integrated primary zones on DC01:
- `ad.bytegeist.lab`
- `_msdcs.ad.bytegeist.lab`
- Three default reverse-lookup zones
Clients resolve the domain through DC01. The PDC Emulator (DC01) now synchronizes time externally from `time.windows.com`, `pool.ntp.org`, and `time.nist.gov` — a fix I applied during this audit (see Problems and Fixes).
## Organizational units
```
ad.bytegeist.lab/
├── ByteGeist/
│ ├── Groups
│ ├── Servers
│ ├── Workstations
│ └── Users/
│ ├── HR
│ ├── IT
│ └── Sales
└── Domain Controllers
```
## Users and groups
Seven lab user accounts distributed across HR, IT, and Sales OUs. All are lab accounts — no production identities or real personal data.
| OU | Users |
|---|---|
| HR | jwilson, ldavis |
| IT | bsmith, kcasko, sjohnson |
| Sales | mbrown, tmiller |
Seven global security groups under `OU=Groups,OU=ByteGeist`:
> Accounting · Help Desk · HR Employees · IT Employees · Management · Sales Employees · VPN Users
Groups are the access-control building block the lab uses — accounts never get rights directly on resources; groups do.
## File services
FILE01 publishes one departmental share:
| Share | Path | Share-level ACL | NTFS ACL |
|---|---|---|---|
| `IT` | `C:\Shares\IT` | Domain Admins = Full; IT Employees = Change | IT Employees = Modify (explicit); SYSTEM / Administrators = Full (inherited); Users = ReadAndExecute + CreateFiles + AppendData |
Role-based access via group membership: only members of `BGLAB\IT Employees` get write access to the IT share, with a conservative share-level cap at Change (no share-level Full for regular users). HR and Sales shares aren't published yet; they're planned work.
## Client domain join
WIN11-01 is in AD as a domain-joined Windows 11 Education client, last successful domain logon 2026-08-05. Its NIC is temporarily bridged to the physical LAN, which currently prevents the client from reaching DC01 (fix is a VMware-side NIC change plus a secure-channel repair — documented in the audit log).
## Networking
- **VMnet8 (NAT, 192.168.31.0/24)** — hosts DC01, FILE01, and OPNsense's WAN interface.
- **VMnet2 (host-only, 192.168.254.0/24)** — OPNsense LAN segment, intended home for domain clients.
- OPNsense is the lab's router/firewall between those segments. The current topology still has servers on VMnet8 rather than behind OPNsense's LAN — honest trade-off I kept so audit traffic stays uncomplicated during build-out.
## Validation tests
Run from DC01 as `BGLAB\Administrator`, output captured to transcripts on the host:
- `Get-ADDomain`, `Get-ADForest`, `Get-ADDomainController` — forest/domain/role data.
- `Get-ADOrganizationalUnit -Filter *` — OU inventory.
- `Get-ADUser -Filter *` + `Get-ADGroup -Filter *` — identity inventory.
- `Get-ADComputer -Filter * -Properties OperatingSystem, LastLogonDate` — domain members and freshness.
- `Get-DnsServerZone` — zone list.
- `dcdiag /q` — DC health (silent = healthy after the SystemLog fix).
- `repadmin /replsummary` — replication (clean on a single-DC forest).
- `w32tm /query /source` and `/status` — time hierarchy, verified moving from `Local CMOS Clock` to `time.windows.com` (stratum 5).
- `Invoke-Command FILE01 { Get-SmbShare | Get-SmbShareAccess ; Get-Acl }` — share and NTFS evidence.
- `Test-ComputerSecureChannel` on FILE01 → `True`.
## Problems found
1. **PDC time source was `Local CMOS Clock`.** On a Windows forest the PDC Emulator is the authoritative time source; every member chains off it. If it drifts, Kerberos tickets outside the 5-minute skew window fail — a classic Help Desk "I can't log in" root cause.
2. **Stale `dcdiag` SystemLog failure** from an unexpected shutdown on 2026-08-07.
3. **My daily account (`keith`) was a standard Domain User** and couldn't WinRM into FILE01 for remote auditing (correct behavior — only Domain Admins are in the server's local Administrators by default).
4. **WIN11-01's NIC drifted to bridged mode**, which severed its path to DC01.
5. **Topology placement:** DC01 and FILE01 sit on NAT (VMnet8) rather than behind OPNsense's LAN, so OPNsense doesn't see server-to-server east-west traffic. Honest reality, not a bug.
## Fixes performed
- Set external NTP on the PDC: `w32tm /config /manualpeerlist:"time.windows.com,0x9 pool.ntp.org,0x9 time.nist.gov,0x9" /syncfromflags:manual /reliable:yes /update`, `Restart-Service W32Time`, `w32tm /resync /rediscover`. Verified: `w32tm /query /source` now returns `time.windows.com,0x9`, stratum 5.
- Cleared the stale System event log (`wevtutil cl System`); re-ran `dcdiag /q` — clean.
- Added `keith` to `Domain Admins` as a documented lab-maintenance action so future audits run as my daily account instead of needing an Administrator sign-in each time. Lab-only elevation; this account has no production use.
Pending (user-side VMware GUI action, not scripted):
- Decrypt WIN11-01's vmx (VM → Access Control → Remove Encryption).
- Switch WIN11-01's network adapter from Bridged to NAT.
- `ipconfig /release && /renew`, point DNS at `192.168.31.10`, `Test-ComputerSecureChannel -Repair`.
## Security considerations
- Lab is isolated behind VMware NAT. No inbound exposure to the host network or the internet.
- Audit transcripts live on the host under `D:\Repos\ad-lab\transcripts\`, not inside a VM.
- No passwords, DSRM, krbtgt, or SIDs are captured in any artifact linked from the portfolio.
- Lab AD is deliberately separate from any production or hybrid identity; nothing in `ad.bytegeist.lab` has internet-facing roles.
## Skills demonstrated
Windows Server 2022 administration · Active Directory Domain Services · DNS · OU and group design · users and groups · SMB file services · NTFS and share permissions · PowerShell (`Get-AD*`, `Invoke-Command`, `w32tm`, `Get-SmbShareAccess`, `Get-Acl`) · VMware Workstation Pro 17 · network segmentation with OPNsense · WinRM remoting · structured troubleshooting · writing honest audit documentation.
## Future improvements
- Move DC01 and FILE01 behind OPNsense (VMnet2) so firewall rules actually see server-side traffic — foundation for the Net+/Sec+ firewall drills in my `opnsense-lab-networking` skill.
- Publish HR and Sales shares with the same RBAC pattern already proven on the IT share.
- Add a first GPO (desktop wallpaper or password policy) linked to `OU=Users,OU=ByteGeist`.
- Enable the AD Recycle Bin and run user-delete / restore drills.
- Build out `baseline` / `baseline-post-drills` snapshots on all three VMs for repeatable break/fix practice.
+285
View File
@@ -0,0 +1,285 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ByteGeist Windows Server / AD Homelab &mdash; Keith Casko</title>
<meta name="description" content="A verified Windows Server 2022 Active Directory homelab: DC01 with AD DS and DNS, FILE01 with role-based SMB shares, a Windows 11 domain client, and OPNsense firewall segmentation. Audited with PowerShell and WinRM." />
<link rel="stylesheet" href="css/styles.css" />
</head>
<body>
<header class="site-header" role="banner">
<div class="container">
<div class="brand">
<span class="name">Keith Casko</span>
<span class="tagline">
IT Support &nbsp;|&nbsp; Systems Administration &nbsp;|&nbsp; Cloud Operations
<span class="location">Kalamazoo, MI</span>
</span>
</div>
<button class="nav-toggle" aria-expanded="false" aria-controls="primary-nav">Menu</button>
<nav class="site-nav" id="primary-nav" aria-label="Primary">
<ul>
<li><a href="index.html#home">Home</a></li>
<li><a href="index.html#projects" class="active">Projects</a></li>
<li><a href="index.html#homelab">Homelab</a></li>
<li><a href="index.html#troubleshooting">Troubleshooting</a></li>
<li><a href="index.html#about">About</a></li>
<li><a href="index.html#resume">Resume</a></li>
<li><a href="index.html#contact">Contact</a></li>
</ul>
</nav>
</div>
</header>
<main>
<section class="hero" id="top" aria-labelledby="lab-title">
<div class="container">
<div class="lab-hero">
<div class="lab-hero-text">
<p class="eyebrow"><a href="index.html#projects">&larr; Projects</a></p>
<h1 id="lab-title">ByteGeist Windows Server / AD Homelab</h1>
<p class="lede">
A multi-VM Windows Server 2022 Active Directory environment I run on
VMware Workstation Pro to practice day-to-day Help Desk and Junior
SysAdmin work: domain services, DNS, OU and group design, SMB file
sharing with role-based access, PowerShell troubleshooting, and the
kind of break/fix that shows up in interview questions.
</p>
<p>
Everything on this page was captured from the live lab on
<strong>2026-10-03</strong>. No fabricated screenshots, no stock art.
</p>
<div class="lab-tags">
<span>Windows Server 2022</span>
<span>Active Directory DS</span>
<span>DNS</span>
<span>SMB &amp; NTFS</span>
<span>PowerShell / WinRM</span>
<span>VMware Workstation</span>
<span>OPNsense</span>
</div>
</div>
<figure class="lab-hero-figure">
<img src="assets/images/homelab-topology.svg"
alt="Topology diagram: DC01 (192.168.31.10) and FILE01 (192.168.31.20) on VMnet8/NAT, OPNsense between VMnet8 and VMnet2, WIN11-01 domain-joined client" />
<figcaption>Verified topology &mdash; generated from <code>ipconfig</code>, <code>Get-ADDomain</code>, <code>Get-SmbShare</code>, and VMware <code>vmnetdhcp.conf</code>.</figcaption>
</figure>
</div>
</div>
</section>
<section id="systems" aria-labelledby="systems-title">
<div class="container">
<div class="section-head">
<h2 id="systems-title">Systems</h2>
<span class="subtitle">Four VMs, verified from <code>vmrun</code> and in-guest audits</span>
</div>
<div class="lab-table-wrap">
<table class="lab-table">
<thead>
<tr><th>System</th><th>Operating System</th><th>Role</th><th>Address</th><th>Purpose</th></tr>
</thead>
<tbody>
<tr><td><strong>DC01</strong></td><td>Windows Server 2022 Standard</td><td>Domain Controller</td><td>192.168.31.10</td><td>AD DS, DNS, PDC Emulator, Schema &amp; Domain Naming Master, Global Catalog</td></tr>
<tr><td><strong>FILE01</strong></td><td>Windows Server 2022 Standard</td><td>Member server</td><td>192.168.31.20</td><td>SMB file services; <code>IT</code> departmental share</td></tr>
<tr><td><strong>WIN11-01</strong></td><td>Windows 11 Education</td><td>Domain client</td><td><em>NIC change pending</em></td><td>Domain-joined workstation</td></tr>
<tr><td><strong>OPNSENSE</strong></td><td>OPNsense (FreeBSD)</td><td>Firewall / router</td><td>VMnet8 &harr; VMnet2</td><td>Segmenting server (VMnet8) and client (VMnet2) networks</td></tr>
</tbody>
</table>
</div>
</div>
</section>
<section id="ad" aria-labelledby="ad-title">
<div class="container">
<div class="section-head">
<h2 id="ad-title">Active Directory &amp; DNS</h2>
<span class="subtitle">Captured from <code>Get-ADDomain</code> / <code>Get-ADForest</code> on DC01</span>
</div>
<div class="lab-grid-2">
<div class="lab-panel">
<h3>Forest &amp; Domain</h3>
<ul class="kv">
<li><span>Forest / Domain</span><code>ad.bytegeist.lab</code></li>
<li><span>NetBIOS</span><code>BGLAB</code></li>
<li><span>Forest mode</span><code>Windows2016Forest</code></li>
<li><span>Domain mode</span><code>Windows2016Domain</code></li>
<li><span>FSMO roles</span>all held by <code>DC01</code></li>
<li><span>Global Catalog</span><code>DC01</code></li>
<li><span>DNS zones</span><code>ad.bytegeist.lab</code>, <code>_msdcs.ad.bytegeist.lab</code>, 3 reverse</li>
<li><span>PDC time source</span><code>time.windows.com</code> (fixed from <code>Local CMOS</code>)</li>
</ul>
</div>
<div class="lab-panel">
<h3>Organizational Units</h3>
<pre class="lab-tree">ad.bytegeist.lab/
├── ByteGeist/
│ ├── Groups
│ ├── Servers
│ ├── Workstations
│ └── Users/
│ ├── HR
│ ├── IT
│ └── Sales
└── Domain Controllers</pre>
<h3 class="h3-sub">Lab-created groups</h3>
<p class="mono-list">
Accounting &middot; Help Desk &middot; HR Employees &middot;
IT Employees &middot; Management &middot; Sales Employees &middot;
VPN Users
</p>
</div>
</div>
</div>
</section>
<section id="files" aria-labelledby="files-title">
<div class="container">
<div class="section-head">
<h2 id="files-title">File services &amp; permissions</h2>
<span class="subtitle">FILE01 &mdash; <code>Get-SmbShareAccess</code> and <code>Get-Acl</code></span>
</div>
<p>
FILE01 publishes one departmental share and uses the <code>IT Employees</code>
security group to grant access &mdash; accounts never get rights directly on
resources, groups do. The share-level cap is <strong>Change</strong>; NTFS
grants <strong>Modify</strong> explicitly to <code>BGLAB\IT&nbsp;Employees</code>.
</p>
<div class="lab-grid-2">
<div class="lab-panel">
<h3>Share <code>IT</code> at <code>C:\Shares\IT</code></h3>
<h4>Share-level ACL</h4>
<table class="lab-table lab-table-sm">
<thead><tr><th>Account</th><th>Type</th><th>Right</th></tr></thead>
<tbody>
<tr><td><code>BGLAB\Domain Admins</code></td><td>Allow</td><td>Full</td></tr>
<tr><td><code>BGLAB\IT Employees</code></td><td>Allow</td><td>Change</td></tr>
</tbody>
</table>
<h4>NTFS ACL</h4>
<table class="lab-table lab-table-sm">
<thead><tr><th>Identity</th><th>Rights</th><th>Inherited</th></tr></thead>
<tbody>
<tr><td><code>BGLAB\IT Employees</code></td><td>Modify, Synchronize</td><td>No (explicit)</td></tr>
<tr><td><code>NT AUTHORITY\SYSTEM</code></td><td>FullControl</td><td>Yes</td></tr>
<tr><td><code>BUILTIN\Administrators</code></td><td>FullControl</td><td>Yes</td></tr>
<tr><td><code>BUILTIN\Users</code></td><td>ReadAndExecute + CreateFiles + AppendData</td><td>Yes</td></tr>
<tr><td><code>CREATOR OWNER</code></td><td>Full on child objects</td><td>Yes</td></tr>
</tbody>
</table>
</div>
<div class="lab-panel">
<h3>How it was verified</h3>
<pre class="lab-code">PS&gt; Invoke-Command FILE01 {
Get-SmbShare |
Where-Object Name -NotIn 'ADMIN$','C$','IPC$' |
Get-SmbShareAccess
(Get-Acl C:\Shares\IT).Access
}</pre>
<p>
Run from DC01 as a Domain Admin via WinRM, output captured to a transcript
on the host (not inside the VM) so no sensitive data lives on a shared
share.
</p>
</div>
</div>
</div>
</section>
<section id="validation" aria-labelledby="validation-title">
<div class="container">
<div class="section-head">
<h2 id="validation-title">Validation &amp; fixes applied</h2>
<span class="subtitle">Real problems found &amp; resolved during the audit</span>
</div>
<div class="lab-grid-2">
<div class="lab-panel">
<h3>Problem: PDC was using the local CMOS clock</h3>
<p>
The PDC Emulator is the authoritative time source for a Windows forest.
If it drifts, Kerberos tickets outside the 5-minute skew window fail &mdash;
a classic "I can't log in" root cause. <code>w32tm /query /source</code>
returned <code>Local CMOS Clock</code>.
</p>
<pre class="lab-code">w32tm /config /manualpeerlist:"time.windows.com,0x9 pool.ntp.org,0x9 time.nist.gov,0x9" `
/syncfromflags:manual /reliable:yes /update
Restart-Service W32Time
w32tm /resync /rediscover</pre>
<p class="status-ok">Verified: <code>Source: time.windows.com,0x9</code>, Stratum 5.</p>
</div>
<div class="lab-panel">
<h3>Problem: stale <code>dcdiag</code> SystemLog failure</h3>
<p>
A past unexpected shutdown left an entry that <code>dcdiag</code> flagged on
every run. Cleared the System log and re-ran <code>dcdiag /q</code>.
</p>
<pre class="lab-code">wevtutil cl System
dcdiag /q</pre>
<p class="status-ok">Verified: <code>dcdiag /q</code> now silent (clean).</p>
<h3 class="h3-sub">Pending (user-side VMware GUI)</h3>
<p>
WIN11-01's vmx is encrypted and its NIC is bridged to the physical LAN
(192.168.1.132), so it currently can't reach DC01 (192.168.31.10). Fix is a
VMware-side NIC change plus a <code>Test-ComputerSecureChannel -Repair</code>.
Documented honestly rather than papered over.
</p>
</div>
</div>
</div>
</section>
<section id="skills" aria-labelledby="skills-title">
<div class="container">
<div class="section-head">
<h2 id="skills-title">Skills demonstrated</h2>
<span class="subtitle">Why this project matters for IT roles</span>
</div>
<ul class="lab-skill-list">
<li><strong>Windows Server 2022</strong> &mdash; installed, promoted to a DC, operate day-to-day.</li>
<li><strong>Active Directory</strong> &mdash; domain / forest design, OUs, users and groups, FSMO awareness, Global Catalog.</li>
<li><strong>DNS</strong> &mdash; AD-integrated primary zones, reverse zones, understanding why the client's DNS must point at the DC.</li>
<li><strong>SMB &amp; NTFS</strong> &mdash; share creation, share-level vs. NTFS permissions, role-based access through groups.</li>
<li><strong>PowerShell</strong> &mdash; <code>Get-AD*</code>, <code>Invoke-Command</code>, <code>Get-SmbShareAccess</code>, <code>Get-Acl</code>, <code>w32tm</code>, <code>Test-ComputerSecureChannel</code>.</li>
<li><strong>Troubleshooting</strong> &mdash; recognizing <em>Local CMOS Clock</em> as a future Kerberos failure; recognizing an Access Denied on WinRM as "not in the server's local Administrators."</li>
<li><strong>Virtualization &amp; networking</strong> &mdash; VMware Workstation Pro, VMnet subnetting, OPNsense placement, bridged vs. NAT NIC implications.</li>
<li><strong>Honest audit documentation</strong> &mdash; the <code>WIN11-01 pending</code> callout stays visible, with the exact fix listed.</li>
</ul>
</div>
</section>
<section>
<div class="container">
<div class="contact-cta">
<div>
<h2>Want to see the full audit log?</h2>
<p>Phases, verified command output, problem-and-fix table, security notes.</p>
</div>
<div class="contact-actions">
<a class="btn btn-primary" href="docs/windows-server-homelab.md">Project write-up</a>
<a class="btn btn-secondary" href="docs/homelab-audit.md">Full audit log</a>
</div>
</div>
</div>
</section>
</main>
<footer class="site-footer" role="contentinfo">
<div class="container">
<div>&copy; <span id="year">2026</span> Keith Casko. All rights reserved.</div>
<ul class="footer-links">
<li><a href="assets/resume/Keith_Casko_IT_Cloud_Resume.docx" download>Resume</a></li>
<li><a href="https://github.com/kcasko" rel="noopener">GitHub</a></li>
<li><a href="https://www.linkedin.com/in/keith-casko/" rel="noopener">LinkedIn</a></li>
<li><a href="mailto:keith.casko@gmail.com">Email</a></li>
</ul>
</div>
</footer>
<script src="js/main.js" defer></script>
</body>
</html>
+513
View File
@@ -0,0 +1,513 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Keith Casko &mdash; IT Support, Systems Administration, Cloud Operations</title>
<meta name="description" content="Keith Casko &mdash; IT portfolio: Windows Server, Active Directory, Linux, AWS, Docker, networking, and troubleshooting projects. Based in Kalamazoo, Michigan." />
<link rel="stylesheet" href="css/styles.css" />
</head>
<body>
<!-- ============ Header ============ -->
<header class="site-header" role="banner">
<div class="container">
<div class="brand">
<span class="name">Keith Casko</span>
<span class="tagline">
IT Support &nbsp;|&nbsp; Systems Administration &nbsp;|&nbsp; Cloud Operations
<span class="location">Kalamazoo, MI</span>
</span>
</div>
<button class="nav-toggle" aria-expanded="false" aria-controls="primary-nav">Menu</button>
<nav class="site-nav" id="primary-nav" aria-label="Primary">
<ul>
<li><a href="#home" class="active">Home</a></li>
<li><a href="#projects">Projects</a></li>
<li><a href="#homelab">Homelab</a></li>
<li><a href="#troubleshooting">Troubleshooting</a></li>
<li><a href="#about">About</a></li>
<li><a href="#resume">Resume</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
</nav>
</div>
</header>
<main>
<!-- ============ Hero ============ -->
<section class="hero" id="home" aria-labelledby="hero-title">
<div class="container">
<div class="hero-grid">
<div>
<h1 id="hero-title">Building Reliable Systems.<br />Solving Real Problems.</h1>
<p class="lede">
Hands-on experience with Windows Server, Active Directory, Linux, AWS,
networking, Docker, monitoring, remote administration, and technical
troubleshooting.
</p>
<p>
Currently completing a B.S. in Software Engineering at Western Governors
University while building practical infrastructure and support experience
through a dedicated homelab, AWS projects, and ongoing study of systems
administration and cloud operations.
</p>
<div class="hero-actions">
<a class="btn btn-primary" href="#projects">View Projects</a>
<a class="btn btn-secondary" href="assets/resume/Keith_Casko_IT_Cloud_Resume.docx" download>Download Resume</a>
</div>
</div>
<div class="hero-image">
<img src="assets/images/hero-server-rack.png" alt="Home server rack and homelab workspace" />
</div>
</div>
</div>
</section>
<!-- ============ Featured Projects ============ -->
<section id="projects" aria-labelledby="projects-title">
<div class="container">
<div class="section-head">
<h2 id="projects-title">Featured Projects</h2>
<span class="subtitle">Hands-on infrastructure, support, and cloud work</span>
</div>
<div class="projects-grid">
<article class="project-card">
<a class="card-link" href="homelab.html" aria-label="View ByteGeist Windows Server Lab details">
<div class="thumb thumb-diagram">
<img src="assets/images/homelab-topology.svg"
alt="ByteGeist AD homelab topology diagram — DC01, FILE01, OPNsense, WIN11-01" />
</div>
</a>
<div class="body">
<h3>ByteGeist Windows Server Lab</h3>
<p>
Windows Server 2022 Active Directory lab in VMware: domain
controller with AD DS and DNS, member file server with
role-based SMB shares, Windows 11 domain client, and an
OPNsense firewall segmenting the networks. Audited and fixed
real problems (PDC time source, stale event log) via
PowerShell and WinRM.
</p>
<a class="view-link" href="homelab.html">View Lab Details</a>
</div>
</article>
<article class="project-card">
<div class="thumb">
<img src="assets/screenshots/bytegeist-support-live.png"
alt="ByteGeist Support Lab &mdash; live app screenshot" />
</div>
<div class="body">
<h3>ByteGeist Support Lab</h3>
<p>
An interactive IT troubleshooting application on AWS (Amplify,
Lambda, API Gateway, DynamoDB) with React. Realistic support
incidents, command-line workflows, diagnosis, resolution, and
scoring.
</p>
<a class="view-link" href="https://supportlab.casko.dev/" rel="noopener">View Live Site</a>
</div>
</article>
<article class="project-card">
<div class="thumb">
<img src="assets/screenshots/bytegeist-infrastructure-live.png"
alt="ByteGeist Infrastructure Lab live control plane showing host telemetry, container health, and service status"
style="object-position: top center;" />
</div>
<div class="body">
<h3>ByteGeist Infrastructure Lab</h3>
<p>
A self-hosted Hetzner Ubuntu environment running Docker-based
services with Prometheus, node_exporter, cAdvisor, Grafana, Loki,
Authentik, Gitea, Woodpecker CI, TLS routing, and a sanitized live
status API. Built to practice deployment, monitoring, identity,
security, recovery, and day-to-day infrastructure operations.
</p>
<a class="view-link" href="https://bytegeist.casko.dev/" rel="noopener">View Live Control Plane</a>
</div>
</article>
<article class="project-card">
<div class="thumb">
<img src="assets/screenshots/aws-tracker.png"
alt="AWS Cloud Study Tracker &mdash; live app screenshot" />
</div>
<div class="body">
<h3>AWS Cloud Study Tracker</h3>
<p>
A serverless AWS CRUD application built with Amplify, API Gateway,
Lambda, DynamoDB, and IAM. Used to practice AWS serverless
architecture, permissions, and least-privilege access.
</p>
<a class="view-link" href="https://production.d2kf0c9e1fogq3.amplifyapp.com/" rel="noopener">View Live Site</a>
</div>
</article>
</div>
</div>
</section>
<!-- ============ What I Work With ============ -->
<section id="homelab" aria-labelledby="skills-title">
<div class="container">
<div class="section-head">
<h2 id="skills-title">What I Work With</h2>
<span class="subtitle">Tools, platforms, and areas of practical experience</span>
</div>
<div class="skills-grid">
<div class="skill-card">
<div class="skill-head">
<svg class="ico" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<path d="M3 5.5 11 4v8H3V5.5zM13 3.75 21 2.5V12h-8V3.75zM3 13h8v7L3 18.5V13zm10 0h8v8.5L13 20v-7z"/>
</svg>
<h3>Windows &amp; Active Directory</h3>
</div>
<ul>
<li>Windows 10 / 11</li>
<li>Windows Server 2022</li>
<li>Active Directory</li>
<li>Users &amp; groups, OUs</li>
<li>Domain joins</li>
<li>File shares &amp; permissions</li>
<li>DNS</li>
</ul>
</div>
<div class="skill-card">
<div class="skill-head">
<svg class="ico" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<rect x="3" y="4" width="18" height="16" rx="1.5"/>
<path d="m7 9 3 3-3 3M12 15h5"/>
</svg>
<h3>Linux</h3>
</div>
<ul>
<li>Ubuntu</li>
<li>WSL2</li>
<li>Bash</li>
<li>SSH</li>
<li>Linux administration</li>
</ul>
</div>
<div class="skill-card">
<div class="skill-head">
<svg class="ico" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M7 18a4 4 0 0 1-.9-7.9A6 6 0 0 1 18 10.5a3.5 3.5 0 0 1-.5 7H7z"/>
</svg>
<h3>AWS</h3>
</div>
<ul>
<li>EC2, S3, IAM</li>
<li>Lambda</li>
<li>API Gateway</li>
<li>DynamoDB</li>
<li>Amplify</li>
<li>Systems Manager</li>
<li>KMS</li>
</ul>
</div>
<div class="skill-card">
<div class="skill-head">
<svg class="ico" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<circle cx="12" cy="4" r="2"/>
<circle cx="4" cy="20" r="2"/>
<circle cx="20" cy="20" r="2"/>
<path d="M12 6v6M12 12l-7 6M12 12l7 6"/>
</svg>
<h3>Networking</h3>
</div>
<ul>
<li>TCP/IP, IPv4 / IPv6</li>
<li>DNS, DHCP</li>
<li>SSH, HTTP/HTTPS, TLS</li>
<li>VPNs</li>
<li>Reverse proxies</li>
<li>Firewalls</li>
</ul>
</div>
<div class="skill-card">
<div class="skill-head">
<svg class="ico" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M4 14v-2a8 8 0 1 1 16 0v2"/>
<rect x="2.5" y="14" width="4.5" height="6" rx="1"/>
<rect x="17" y="14" width="4.5" height="6" rx="1"/>
<path d="M17 20a3 3 0 0 1-3 3h-2"/>
</svg>
<h3>IT Support</h3>
</div>
<ul>
<li>Troubleshooting</li>
<li>Customer &amp; remote support</li>
<li>Technical communication</li>
<li>Incident resolution</li>
<li>Permissions &amp; authentication</li>
<li>Connectivity testing</li>
</ul>
</div>
<div class="skill-card">
<div class="skill-head">
<svg class="ico" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<rect x="3" y="4" width="18" height="5" rx="1"/>
<rect x="3" y="11" width="18" height="5" rx="1"/>
<rect x="3" y="18" width="18" height="3" rx="1"/>
<path d="M6.5 6.5h.01M6.5 13.5h.01"/>
</svg>
<h3>Infrastructure</h3>
</div>
<ul>
<li>Docker, Docker Compose</li>
<li>VirtualBox</li>
<li>Portainer</li>
<li>Grafana, Prometheus</li>
<li>Loki</li>
<li>Uptime Kuma</li>
</ul>
</div>
<div class="skill-card">
<div class="skill-head">
<svg class="ico" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<rect x="2.5" y="4" width="19" height="12" rx="1.5"/>
<path d="M8 20h8M12 16v4"/>
</svg>
<h3>Remote Administration</h3>
</div>
<ul>
<li>RDP</li>
<li>Parsec</li>
<li>Tailscale</li>
<li>RealVNC</li>
</ul>
</div>
<div class="skill-card">
<div class="skill-head">
<svg class="ico" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="m8 7-5 5 5 5M16 7l5 5-5 5M14 5l-4 14"/>
</svg>
<h3>Scripting &amp; Tools</h3>
</div>
<ul>
<li>PowerShell</li>
<li>Bash</li>
<li>Git</li>
<li>GitHub</li>
</ul>
</div>
</div>
</div>
</section>
<!-- ============ Troubleshooting Notes ============ -->
<section id="troubleshooting" aria-labelledby="notes-title">
<div class="container">
<div class="section-head">
<h2 id="notes-title">Troubleshooting Notes</h2>
<span class="subtitle">Short, practical case studies</span>
</div>
<div class="notes-list">
<article class="note-item">
<div class="icon" aria-hidden="true">DNS</div>
<div>
<h3>DNS Resolution Issue</h3>
<p>Client cannot reach a service by name but can reach it by IP &mdash; isolate DNS from general network connectivity.</p>
<ul>
<li>Confirm TCP/IP configuration with <code>ipconfig /all</code></li>
<li>Verify DNS server settings and search suffix</li>
<li>Test reachability with <code>ping</code> against both hostname and IP</li>
<li>Use <code>nslookup</code> against the primary and a known-good DNS server</li>
<li>Flush client resolver cache; compare behavior from another host</li>
</ul>
</div>
<div class="chevron" aria-hidden="true">&rsaquo;</div>
</article>
<article class="note-item">
<div class="icon" aria-hidden="true">DKR</div>
<div>
<h3>Docker Networking Problem</h3>
<p>A container responds locally but is unreachable from other hosts, or outbound requests fail.</p>
<ul>
<li>Check container state with <code>docker ps</code> and <code>docker logs</code></li>
<li>Verify published ports and the attached Docker network</li>
<li>Confirm DNS resolution from inside the container</li>
<li>Check host firewall rules affecting the bridge or published ports</li>
<li>Test HTTP endpoints with <code>curl -v</code> from host and container</li>
</ul>
</div>
<div class="chevron" aria-hidden="true">&rsaquo;</div>
</article>
<article class="note-item">
<div class="icon" aria-hidden="true">AD</div>
<div>
<h3>Active Directory Permissions Issue</h3>
<p>A user authenticates successfully but cannot access a shared folder they should.</p>
<ul>
<li>Confirm the user's identity and group membership</li>
<li>Review share permissions and NTFS permissions separately</li>
<li>Check for deny ACEs that override group access</li>
<li>Validate authentication path and session with <code>whoami /groups</code></li>
<li>Test access from a known-good account to isolate user vs. share</li>
</ul>
</div>
<div class="chevron" aria-hidden="true">&rsaquo;</div>
</article>
<article class="note-item">
<div class="icon" aria-hidden="true">IAM</div>
<div>
<h3>AWS IAM Access Problem</h3>
<p>A workload or user receives <em>AccessDenied</em> when calling an AWS service.</p>
<ul>
<li>Identify the exact action, resource, and principal from the error</li>
<li>Review attached identity and resource policies against least privilege</li>
<li>Check for explicit denies, SCPs, and permission boundaries</li>
<li>Reproduce with the IAM Policy Simulator</li>
<li>Grant only the specific action needed; verify, then narrow further</li>
</ul>
</div>
<div class="chevron" aria-hidden="true">&rsaquo;</div>
</article>
</div>
</div>
</section>
<!-- ============ About ============ -->
<section id="about" aria-labelledby="about-title">
<div class="container">
<div class="section-head">
<h2 id="about-title">About</h2>
<span class="subtitle">Background and focus</span>
</div>
<div class="about-grid">
<div class="about-photo">
<img src="assets/images/keith-casko-headshot.png"
alt="Keith Casko"
class="about-headshot" />
</div>
<div class="about-text">
<h3>Keith Casko &mdash; Kalamazoo, Michigan</h3>
<p>
I'm transitioning into IT, cloud, and systems administration while
completing a B.S. in Software Engineering at Western Governors
University. My focus is practical, hands-on infrastructure work:
Windows Server and Active Directory, Linux, AWS, Docker, networking,
and technical troubleshooting.
</p>
<p>
My professional background is at Costco Wholesale as a Baker. The job
is production-paced and team-based, and it's where I developed the
habits I bring to IT work &mdash; customer service, teamwork, training
coworkers, process discipline, prioritization, and real-world
problem-solving under pressure.
</p>
</div>
<aside class="pull-quote" aria-label="Approach">
<span class="mark">&ldquo;</span>
Reliable systems are built one careful change at a time. I'd rather
understand a problem than paper over it &mdash; and I document what I
learn so the next person has a shorter path.
</aside>
</div>
</div>
</section>
<!-- ============ Education & Experience ============ -->
<section id="resume" aria-labelledby="resume-title">
<div class="container">
<div class="section-head">
<h2 id="resume-title">Education &amp; Experience</h2>
<span class="subtitle">Current study and professional background</span>
</div>
<div class="two-col">
<div class="panel">
<h3>Western Governors University</h3>
<div class="meta">Bachelor of Science, Software Engineering &middot; In Progress</div>
<h4>Relevant Study</h4>
<ul>
<li>Cloud Computing</li>
<li>Networking</li>
<li>IT Operations</li>
<li>Software Development</li>
<li>Java</li>
<li>Web Development</li>
<li>Security Fundamentals</li>
</ul>
</div>
<div class="panel">
<h3>Costco Wholesale &mdash; Baker</h3>
<div class="meta">June 2015 &ndash; Present</div>
<h4>Transferable Experience</h4>
<ul>
<li>High-volume production environment</li>
<li>Accuracy and process discipline</li>
<li>Prioritization under time pressure</li>
<li>Day-to-day troubleshooting of equipment and workflows</li>
<li>Coordinating with team members and supervisors</li>
<li>Training coworkers on procedures</li>
<li>Customer service and clear communication</li>
<li>Problem solving and follow-through</li>
</ul>
</div>
</div>
</div>
</section>
<!-- ============ Contact ============ -->
<section id="contact" aria-labelledby="contact-title">
<div class="container">
<div class="contact-cta">
<div>
<h2 id="contact-title">Open to IT Support, Help Desk, and Junior SysAdmin roles</h2>
<p>Based in Kalamazoo, Michigan &mdash; available on-site, hybrid, or remote.</p>
<p><a href="mailto:keith.casko@gmail.com">keith.casko@gmail.com</a></p>
</div>
<div class="contact-actions">
<a class="btn btn-primary" href="mailto:keith.casko@gmail.com">Email Keith</a>
<a class="btn btn-secondary" href="https://www.linkedin.com/in/keith-casko/" rel="noopener">LinkedIn</a>
</div>
</div>
</div>
</section>
</main>
<!-- ============ Footer ============ -->
<footer class="site-footer" role="contentinfo">
<div class="container">
<div>&copy; <span id="year">2026</span> Keith Casko. All rights reserved.</div>
<ul class="footer-links">
<li><a href="assets/resume/Keith_Casko_IT_Cloud_Resume.docx" download>Resume</a></li>
<li><a href="https://github.com/kcasko" rel="noopener">GitHub</a></li>
<li><a href="https://www.linkedin.com/in/keith-casko/" rel="noopener">LinkedIn</a></li>
<li><a href="mailto:keith.casko@gmail.com">Email</a></li>
</ul>
</div>
</footer>
<script src="js/main.js" defer></script>
</body>
</html>
+1232
View File
File diff suppressed because it is too large Load Diff
+21
View File
@@ -0,0 +1,21 @@
// Minimal JS: mobile nav toggle + active section highlight.
(function () {
var toggle = document.querySelector('.nav-toggle');
var nav = document.querySelector('.site-nav');
if (toggle && nav) {
toggle.addEventListener('click', function () {
var open = nav.classList.toggle('open');
toggle.setAttribute('aria-expanded', open ? 'true' : 'false');
});
nav.addEventListener('click', function (e) {
if (e.target.tagName === 'A' && window.innerWidth <= 640) {
nav.classList.remove('open');
toggle.setAttribute('aria-expanded', 'false');
}
});
}
// Set current year in footer
var y = document.getElementById('year');
if (y) y.textContent = new Date().getFullYear();
})();