Deploy Django: GitOps & Kubernetes Made Easy with Calvin Hendryx-Parker

This video features Calvin Hendryx-Parker at DjangoCon US 2025 in Chicago, Illinois, USA.

Deploy Django: GitOps & Kubernetes Made Easy with Calvin Hendryx-Parker
0:43:47
Published October 23, 2025
451 views

This talk was presented at: https://2025.djangocon.us/talks/deploy-djang-gitops-kubernetes-made-easy/

LINKS:
Follow Calvin Hendryx-Parker ๐Ÿ‘‡
On Mastodon: https://fosstodon.org/@calvinhp
On X: https://x.com/calvinhp
Website: https://sixfeetup.com/

Follow DjangoCon US ๐Ÿ‘‡
https://fosstodon.org/@djangocon
https://x.com/djangocon

Follow DEFNA ๐Ÿ‘‡
https://www.defna.org/

Video production by the presenter and DjangoCon US 2025 volunteers.

Summary

Calvin Hendryx-Parker shows how a Django project can move from an empty repository to a cloud sandbox using a GitOps workflow built around Kubernetes, GitHub Actions, Terraform, Argo CD, and the Scaff project template. Developers work through pull requests and branch changes; CI builds and tags Django and Next.js images, while Argo CD watches the repository and reconciles the cluster without SSH access or manual production commands. He argues that Kubernetes is useful not only for large teams but also for small projects because it provides reproducible environments, local-to-production consistency, automated rollbacks, drift protection, auditability, secrets management, scalable deployments, and reduced cloud-provider lock-in. The demonstration also covers K3s, Nix for consistent cross-platform tooling, sealed secrets, Talos Linux, and the generated Django/PostgreSQL/Redis/Next.js stack, though the recording ends while the deployment pipeline is still running.

Key takeaways

  • GitOps makes Git the source of truth for application code, infrastructure, and deployment configuration.
  • GitHub Actions builds tested, commit-tagged images, while Argo CD continuously reconciles the Kubernetes environment with the repository.
  • Kubernetes can provide consistent local, sandbox, and production environments, along with zero-downtime releases and quick rollbacks.
  • Sealed secrets, OIDC authentication, restricted cluster access, and immutable Talos Linux reduce common deployment and security risks.
  • Scaff and Nix encode project conventions and tool versions so developers can focus on Django code rather than hand-written YAML and machine-specific setup.
  • The demonstrated stack includes Django, PostgreSQL, Redis, a Next.js frontend, observability tools, and supporting services deployed through reusable templates.

Summarised automatically from the transcript.

Chapters

  1. 0:00 Demo Setup and Project Scaffolding The talk opens by creating a fresh Django project, repository, CI pipeline, and Kubernetes-based deployment from scratch.
  2. 4:07 The Case for GitOps GitOps is introduced as a safer alternative to manual server and console-based deployment for increasingly complex applications.
  3. 7:57 GitOps Benefits for Django The speaker covers declarative infrastructure, drift protection, rollback capability, audit trails, and environment consistency for Django applications.
  4. 13:20 Kubernetes for Django Development Kubernetes is presented as a practical platform for local development, reproducibility, cloud portability, scaling, and zero-downtime releases.
  5. 17:59 Argo CD and Continuous Reconciliation The talk explains how Argo CD watches Git repositories and automatically synchronizes Kubernetes environments using manifests, Helm, or Kustomize.
  6. 20:20 Scaffolding the Full-Stack Platform Scaff is introduced as a way to generate an opinionated Django, PostgreSQL, Redis, Next.js, and Kubernetes project ready for day-zero deployment.
  7. 24:15 Developer Workflow and Cross-Platform Tooling The speaker traces the pull-request-driven workflow and explains how Nix standardizes command-line tools across macOS, Linux, and Windows environments.
  8. 28:06 Automated Secrets and Deployment Improvements Recent Scaff improvements include sealed-secret automation, GitHub CLI integrations, automated infrastructure setup, and reduced reliance on manual operations.
  9. 32:46 Argo CD Deployment Demo A live Argo CD environment is used to show managed applications, certificates, PostgreSQL operations, pods, and the deployed Django and Next.js front ends.
  10. 35:54 GitOps Change Propagation The speaker modifies the application, pushes the change, and follows GitHub Actions as it builds images and updates deployment manifests.
  11. 39:08 Container Version Tracking The demo shows how backend and frontend images are tagged by commit and environment so the deployed versions remain identifiable and linked.

Transcript

7,906 words · auto-generated Show

Automatically transcribed, so expect mistakes in names and technical terms.

0:16

So this this talk involves a demo that takes 25 minutes to complete, mostly in the background. So we're going to start off with part of the demo uh and then it all makes sense as we go. Uh I've I've struggled so you don't have to. I've built Probably 20 Kubernetes clusters today alone in preparation for this talk and about 40 for the last time I did this talk just to make sure everything should go as planned. So let's quickly scroll over here. Uh what I've got on my file system, well, is a bunch of demo ones. We're going to make a fresh project. Fresh GitHub repository, fresh CI pipeline, fresh cloud, you name it, we're we're doing that.

1:02

So we're going to create a repo in the 6V repository, and we're going to call this one Django 10 for the 20th iteration of Kubernetes clusters. And we'll make sure it's public. You all can check this out if you go to that that repo as we push. Actually, you'll be able to watch the uh the GitHub actions uh go as we uh along the way too. Next bit is we're actually gonna build this project out. So we're starting again with nothing on the file system. We're gonna template up from a scaffolding, uh a DjangoCon project that is a six feet up full stack opinionated This is how we think things should go on a Django project. And I'll talk about that as well. So Django 10. Oh

1:47

shoot. Of course I mess it up. One typo. I I practice again, I've run this like ten times this morning. You'd think I'd have it down by now. 10, 10, 2, 2, here we go. So and it's actually gonna have DNS to it too. So if I put in here DjangoCon10. scaf, at some point at the end of this demo, you'll be able to go to a URL. That has been published through Route 53, all orchestrated, no uh click salad involved at all, into a specific AWS account Which I can find right there. And I do want to next. js front end. We're going to use uh Kates, so K3S for our Kubernetes, single node Kubernetes.

2:34

And then we're gonna push this into actual GitHub as we go. So into the 6v org. What this is doing behind the scenes is laid down a bunch of files on the file system for a Django project that has a Postgres backend. It's actually running a Kubernetes cluster locally. So during this talk, two Kubernetes clusters will be harmed. The ones running in kind on my local machine. It's going to have the Django part and the Next. js run-in plus the Redis and the and the Postgres pieces in there And it's going to be all with our developer experience piece. So if you have actually followed my talk from like a year and a half ago or two years ago, I did a couple talks on SCAF. from a developer experience standpoint, this is like the next step of that, which is

3:19

great, I've developed stuff. What happens next? So this is the GitOps I'm gonna deploy to sandbox, I'm gonna deploy to production, I want to have an actual product running with a URL that people can get to and have solved all those things. Actually who who in the room loves doing deployment? Like that's their favorite thing. Oh we do have a couple. Okay, sweet. You're my people. Because I I love deployment and I love this stuff, but it can get tricky, obviously, if you've you've have have you been able to deploy from scratch a Kubernetes cluster in 25 minutes uh while on stage? Okay, good. Then you're again my people So we're we're we're in the right spot. Uh we're going to quickly go over here. If you want to check out these slides, uh Ignore the Pie Ohio bit. I did give this talk at Pie Ohio. I didn't have time to make a fresh repo for the talk because they let

4:07

they let me knew I was going to talk up here like Friday. But that QR code goes to the GitHub. If you just go to SixFeetUps GitHub, you can see the talk in there, the slides are in there, all the content's in there, there's a PDF in there. Actually you can click on a link and see this these these slides almost in real time with it as well. And let me double check that things are moving along on the demo because I can't wait too long. It's getting real close. Okay Why why even talk about GitOps? Like we've talked about deployment. I mean back in the old days we used to like SSH into our server. Maybe we telnet it into our server and had a Apache we compiled from source and with a web root and we threw stuff in that folder and man we had a site up and running and it was live and it took no time at all. Well that world has changed. And now we have these complex apps that are actually applications.

4:54

They're not just websites. We're building full-blown apps that are doing work of value for folks. Okay, here this is getting ready to go again. Yes. Right now it's it's actually pinning all of our um Python packages. So by default, Scaff starts fairly unpinned. And as you build new projects, we pin them as you're doing like a greenfield new project so you don't start off with like a bit rotted um state of like your Django and Postgres instances and Reddites and things like that. So I'm gonna wait for this to end because I want to make sure I can keep this moving forward. Django content. And we use as you'll see here I'm using Nix

5:39

to make sure my environments are sane and I'll I'll talk about that too. Oh come on go. I ran this phi again ten times this morning to make sure I wouldn't run into this part of the problem. Um, but I think it's looking pretty good. Alright, there we go. Nice. So we're gonna check this code in. We're gonna push it into GitHub, which is gonna trigger our first GitHub action, which is gonna build some images, which is pretty awesome. Uh git checking this. Here we have net get push And we're gonna do something, we're gonna branch here so we can go working off of our develop branch.

6:25

So we can start establishing a GitOps workflow where Work can be done on developed branch, that can be pushed into sandbox, and when work is done on pushed or merged down to the main branch, that can automatically go into production, for example. Oh, it's waiting for me to do. It's asking me questions over here. I was looking over there. My bad. Git checkout. Develop and we will push develop up too. Oop, not develop, develop. Okay, now we're like fully ready to actually run the magic command, which is, wouldn't it be great if I could just type deploy Sandbox. And that got me a day zero working Django app in the cloud as a sandbox ready to test.

7:11

That's what's going to happen here right now once I actually do this. Sometimes it doesn't like the the log the this login state of the Amazon SSO stuff. So this will actually ask me. It's gonna pop open a browser window. Uh you probably can't see it. Going to accept and continue. So it pop up an OAuth login our window over here and now we're back. add it over here. It's actually going to also use security groups right out of the box to ensure that only my laptop, which is on a VPN, back to a static IP at my house.

7:57

So none of you can mess with me. uh that it's only gonna have that access for the uh the Kubernetes uh control plane and uh any other like Uh like the Argo CD uh bits are all protected and any SSH is also protected. Okay. Now that that's rolling, I'll get into the rest of the talk. Okay. So w with GitOps we get a bunch of big benefit here is that these applications are complicated to deploy. Uh they could be fraught with human prone errors. Anytime someone's a human's in there clicking in the console or even doing CLI type commands, there's always a chance for someone to go in and kind of fat finger something. And we try to avoid that. We want to make this as automated and push button as possible. And the big benefit here too is GitOps gives us this single source of truth.

8:44

There is the uh it contains all of our deployment artifacts, all of our code, all of how we want something to happen, and then it's declarative. It's not going to be how we build something, it is what we want built. So we're using Terraform as one of our opinions, we're using Kubernetes manifests as another set of our opinions. that describe the end result of our environment and then the tools go make that happen uh under the covers for us. That automatic reconciliation gives us the ability to be doing this continuously. So as people would may go in and and try and make configuration changes, we'll actually be able to protect against that level of drift. Because the system is watching for those changes actively and actually going and fixing and putting things back in if someone did something they weren't supposed to. Uh we've got the whole poll-based deployments.

9:29

You can also do like webhook deployments. In the uh there's no more kubectl apply from your laptop. Like thus you don't want people touching your production environment. You didn't want people production touching your production environment when you had shell access to it. You definitely don't want them touching your production environment when they've got a kubec kube configuration file sitting on their file system that could talk to production. So we can actually eliminate that whole level of security issue by now protecting who has access to that Kubernetes configuration file. And as a bonus, we get a beautiful documentation of our infrastructure that runs this application. So under the covers now we know what takes, what 's going to be built out and can be rebuilt out at a moment's notice, well hopefully, uh as we're doing here Let's let's uh check

10:14

in on our process. Yep, so it's actually up there getting all the providers for Terraform currently. And so we get all the documentation that goes along with that and all the testing suite that can go along with that. We can actually now test our build, test our integrations, test our infrastructure pieces. So that sounds great. I would love that for any application. But if we want to specifically talk about why we want to even have GitOps for Django, but Django itself is an application. And so we want to be able to roll back an application. So with GitOps you get the option of I can push changes and preferably roll forward and build new images and deploy those images, but if something goes awry I can now go into my GitOps platform where you this in this case we're deploying Argo CD as part of our GitOps platform.

11:00

And we'll be able to go in there and actually, with one click, redeploy a previous version of an image. We want to build again environment drift protection, I kind of mentioned that. The development environment, the staging environment, the sandbox environment, the production environment can now all stay in sync with one another. And they move forward together. So as I make changes in my local environment, I can now programmatically roll those out into other environments with a process. It's all been codified. Another nice bit here is we're using a CICD um model for this, which means we can use tool uh security tools like OIDC Connect. on GitHub actions to talk to our Amazon infrastructure. And no one has to store a AWS C. How many people love storing and handling AWS secret keys and s and uh

11:47

whatever the other one is called. I I don't even want to deal with them anymore. I want to SSO in my myself and I want the tooling to actually use a similar type of an infrastructure to identify what role it has when it's going and interacting with my infrastructure. And so I can do that now with the CICD pipelines and control this whole thing front to back. And that gives us, obviously, a nice foothold into some compliance pieces. You get a complete audit trail of who's done what, when and where and how. And like I mentioned before, you also control who has access to that kube configuration file, which is with that. You you can't do anything on a production environment, for example. And each environment we so in this case you'll see we're using sealed secrets uh for our uh key storage. Those sealed secrets are tied to specific environments.

12:32

So the sealed secrets for sandbox only work on sandbox. The sealed secrets for production only work on production. And only if you've got the kubectl uh for production. So you've protected that from are you kind of you've given people kind of a least privileged stance on how they should approach this infrastructure. All right, a little between slide check-in. It's going a little slow. We'll see how this Wi-Fi does today. Everybody hold your breath and stop using the Wi-Fi. Okay, so then you now I I I I've kind of avoided the elephant in the room. Like I I know there are folks out here who are not using Kubernetes yet. Who who in the room is not using Kubernetes? Yeah, yeah, I knew it. I knew you were out there. Uh and I th I think there's been reasonable arguments for why that is.

13:20

Uh it it is seen as very complex. maybe overkill, maybe just too much overhead for a small little application. But I'm here to tell you that that has changed. I feel like the tooling has come along and and and actually provides us with a great platform for using this from front to back. Everything, actually, who runs Kubernetes in production but doesn't use it locally? Raise your hand. Yeah, so the same people who said they're using Kubernetes uh are not necessarily using it on their laptop. I'm using it locally and I would in entertain that everyone here or trying convince everyone here that that is actually a great way to develop. Because now the same I can catch issues on my local machine before they ever get into production. Before they ever get to sandbox, and I can iterate as as fast as as I'm running the code locally on my own machine

14:06

But I'm using in in the container environment, I've got all my developer tools, I've got all my like nice environment wrapped around me, and I get to do it because I can use a tool like Kubernetes. I don't I know a lot of people think Kubernetes is this fancy orchestration tool, which it is, but I feel like Kubernetes' real benefit is the control plane, that API programmatic access into being able to control how and when and where and what happens with your deployment of your application. Uh I'll talk about a little more of that later too. But I kind of made like what I thought it would be convincing arguments that you should be running your Django applications under Kubernetes. And the biggest one on my list here is probably actually the bottom one, the cloud agnostic. You have no vendor lock-in. If you've got your stuff deployed in an EC2 instance. Well you're on an EC2 instance, you can't pick up that EC2

14:53

instance and move it over into GCP. Uh it doesn't work that way. You would have to now re redeploy your application and figure out all the manual bits you did along the way to make that happen, where with the tooling we're talking about here in Kubernetes You can be using GKE, which is like the managed Kubernetes from Google. You can be using uh EKS, which is Amazon's EK uh managed Kubernetes. I'm not using either of those. I'm using a cloud agnostic open source Kubernetes distribution to deploy this. And for production, we typically use something like Talos Linux, which has no shell access to the actual virtual machines whatsoever, and the file system is completely immutable. So negating a whole class of security risks and issues that are possible. So we we get, again, I feel like it's the resource efficiency.

15:39

If you do get more load, yeah, there's tools like Carpenter, for example, on Amazon. Actually I think it works in other environments too, that can scale up your number of nodes behind the scenes for you based on whatever metrics or algorithms you you've defined for your application. You know your application best. You're going to know when it needs to scale up, and now it can do it without you intervening, or at least at a controlled fashion that gives you that flexibility. The zero downtime deployments just come out of the box. Like you now can roll out new features, new code, and it will deploy those containers onto the the cluster for you and then wait for all the traffic to go off the other ones, make the new ones live, and there's like basically zero downtime as you go and deploy and deliver these things. And then the kind of list goes on. Like the there's just a lot of benefit I feel like

16:24

Oh, this is not good. This is not going f fast enough at all. We'll see what happens. We we may get a uh uh a deployment. Uh we'll see what happens. And then secrets management. I think that that's another important one because we want nothing left unencrypted as far as a secret goes. When I'm actually deploying up here, you saw it pushed into GitHub. It actually used one, I use OnePassword. I'm a big believer in OnePassword. I love OnePassword. They've got a great command line tool. They've got great integrations with the Mac and the other tooling around it. It actually asked me for my fingerprint to use SSH keys to push my code up into GitHub. There's no private key on my machine at all, other than an encrypted one in the OnePassword vault. Same goes for any of my other secrets that are I'm doing if I did need any kind of API secrets for Amazon.

17:13

But that that allows me then to build The sealed secrets, which is going to be a file generated locally, but using the sealed secrets operator in the cluster to build it so it's attached to that cluster. And then I check that in and it's fully encrypted. There's no plain text passwords passed around anywhere. The cluster knows how to unencrypt it, and that's it. That's the only place it can get unencrypted is in that cluster. And then the deploy story, you know, being able to match the developer environment. Like I can actually now, if if someone reports a bug in production and I can't reproduce it locally, I can just grab this exact same container that's running in production, pull it down to my local machine, and now I've got my developer tools and I can debug and triage. That exact running code. There's no close enough. This is the same container that's running in production

17:59

now running here on my local machine. So how do we get to this GitOps nirvana? Uh this starts with a tool like Argo CD, or you could there's also another one called Flux out there that's open source. There's tons of, I'm sure, commercial options. Argo seems to be the one we've we've landed on, I really like it. Uh it's basically a very powerful wrapper around kubectl and git Uh with a nice UI and lots of pretty like you know imagery that goes along with like having the status and seeing all the containers and seeing all the action. Hopefully if this thing goes uh the as it should. We'll be able to see the kind of Christmas tree of stuff light up into that system as it handles and manages rolling out the deployments for me. And basically it's it's it's Kubernetes native, so it runs inside the Kubernetes

18:46

cluster or some Kubernetes cluster. It has whatever roles and rights are applied to it there. And then it watches those GitHub or Git repos, any Git repo, for changes. So it can sit and pull, it can also have webhooks, but we use the just the standard Look every so often, see if something's changed, uh see if a manifest has changed, see if a new release of the code or new release of the container is out there, and if it is, go handle the kubectl applies to make this thing now live and do it like very s uh hands off for us. So I mentioned that syncing automatically or on demand. You can also push a button and release an old version of a container out there if you wanted to. Uh it has again mentioned nice UI and it supports other tooling too. So if you're using Helm uh customize

19:32

or just plain old YAML, uh it works alongside all those tools really beautifully. Uh we actually have made opinions around all those things. So we use Helm, for example, to deploy Argo C D into our cluster. We use customize to be able to manage the various environments. So I've got a environment set up for local, an environment set up for sandbox, an environment setup for the production and staging But they have very minimal footprint when it comes to amount of that's another objection I think folks folks have had for Kubernetes is going to be the amount of YAML that you gotta write. And I'm I'm not a huge fan of writing YAML either. Luckily tools like customize help minimize that. And I feel like this is all enabled again by the scalf tool. So the very first command I ran after the creating the GitHub repository was a scalf command.

20:20

was a scav command to basically build out this template onto our file system so we could start playing with it. I want to get to day two operation level at day zero. I want to be able to release right away and demo something. I want to have something live that that I can have my stakeholders or business users go click on and try. And not have that be a two-week long process of how do I get this onto the cloud? You know, what technology stack are we going to use? Like we've put together all of our years of experience. in releasing battle-tested production code into this open source scalf product out there. So if you just go to the sixfeetup org on GitHub. slash scaff, you can see that that's the basis of the command line tool. It's got a couple different options for templates.

21:07

So you can actually build your own templates for it and you know codifying your organization's opinions about how these things work And under the covers, it's using uh other open source tooling like copier, for example. Uh for us, this is like cognitive load reduction. You want to focus on your app and not the infrastructure. Us as developers love building code. We don't love building YAML. We don't love deploying. We don't love shelling into a machine. We don't love reading logs. But these toolings you know, wrap around all that and actually make it a little more of a joy, hopefully, uh to do all those things. And I mentioned before, we use Talos Linux typically for our production deployment because it gives us a very minimal, very secure, very immutable set of infrastructure so that we've just negated a whole level of of security attacks.

21:53

Like the attackers are going for low-hanging fruit. I don't want our group or anybody we do work for to become that low-hanging fruit, so we just start off with a good stance, again, day zero. What I love about SCAF , I remember you know I've been developing for a couple years. And I always would love watching the senior devs at their computers. It felt like they weaved magic on their laptops. They they used all the cool tools and all the command line magic wizardry. And I wanted to do all of that. And so we took all that kind of magic and knowledge and kind of put it into a set of conventions so that every developer who works on a SCAF project now has access to rough and black and iSort, has access into you know debugging tools and being able to run a debug instance so you can actually stop your IDE.

22:39

you know, when running in a container inside of Kubernetes and have it all just work and have synchronized files seamlessly. So it's like all the cool tricks and you know tools and things that senior developers get to do, everyone gets to do now because you're using something like uh this tools. Okay, let's cross our fingers. No, shoot. Well, I have a backup plan. It's kind of like the uh baking show. We've uh just shoved out in the oven over there, and we're gonna come over here and grab this one out over here. Uh so figure not, we're we're not stuck. But I will go over that here in a second. Just to kind of visualize this as part of the the GitOps flow, uh you as a developer, really

23:27

your main interactions with all this whole s this whole big piece of machinery is gonna be the pull request. You make pull requests as those pull requests get accepted. Magic happens on the back end to make sure your code gets put into Sandbox or whatever environment where you're gonna do all the testing. From there, that's where like the GitHub Actions handles that. Sends up the images into whatever container registry you want to you know of your choice. We just happen to be using Amazon and then On the other side, the Argo CD controller and the bottom runs in your clusters, watches the GitHub, and when it sees those manifest changes, it knows there's a new image ready to go and it deploys them across. the various pods inside your node. It's really kind of beautiful. And it's easy and as a developer you should love it because you don't have to ever shell into a box again, hopefully.

24:15

Because all the complexities of working with like getting the logs out of your Django instance are now you know make commands or kube kube con kubectl commands to watch the logs or use some GUI with your Kubernetes now and there's some cool tools for being able to develop like that. This didn't come without a little bit of treachery. As the world has moved along and things have diverged from one another, you would think a tool like said would be said everywhere. But I'm here to tell you it's not. There are BSD versions of said. So if you're running one of these fancy fruit devices, you're typically going to out of the box get this BSD said version of it. But if you're running one of the more penguin-y-like devices, you're looking at a GNU version of said. They are different.

25:00

They say the same thing as a title, but they're different in the covers. And the same thing goes for a couple other tools. Like base64 has different flags between BSD and GNU. Uh TR uh has different flags again from these things. So we'd we'd built a lot of infrastructure and a lot of scripting and a lot of things had kind of gone into this, and then we realized Not everything we want to make this again as cross-platform as possible. A person working on a Windows environment, maybe with WSL, should have an equal opportunity as someone working on a Mac using the the Apple silicon or same person who wants to run a Linux desktop full-time. I've done the Linux journey, I've done the Mac journey, I've not done the Windows journey necessarily, but it should be possible for that to be done. And so we've we've settled on a tool called Nix, which also could be a whole nother talk of its own. But Nix

25:46

actually encapsulates per project or per directory or per working area that you're you're you're working in. specific versions of specific tools, they're all pinned just like you pin your Django Python packages. Like we want a specific version of said in this project because maybe we're depending on some deprecated behavior And maybe over in this project we can use the latest and greatest version of said. Uh it's a big terrible example because said doesn't move very fast. So I'm sure that doesn't hasn't happened. But I want to make sure that the binaries are compatible. I want to make sure I'm always using the GNU said everywhere. I want to make sure I'm always using the GNU base64 everywhere, no matter whether I'm on a Mac or if I'm on Linux. And that's what this basically does. It installs all the common tools It makes sure that every developer, if I walk up to another developer's environment in our company

26:33

and I want to use their comp sit down and use their computer, I'm using the exact same version of those tools that are in my working directory for that project. I can move into another project and get different versions of those tools. Maybe you're always on the latest version of Rough, or maybe you're using iSort in this one, not using Rough, and you're using Flake 8 over here, those kinds of opinions can also be encoded so that they're reproducible. And that's what Nix does for us. It makes sure that those common tool versions match and that they're available to every developer who's on the project. And so when I say something to someone on the team, that they aren't Scratching their head and you know spinning their wheels trying to run some kind of product that product like that. So a couple things with Scaff recently uh we've recently decoupled it from one password where we're using One password pretty heavily for all of our secrets management. We moved into just using the sealed secrets only

27:21

and environment variables for passing things around. Again making it more uh agnostic about uh maybe commercial options. I added in a dangerous mode. Uh you don't want to do this. Uh I don't think it's even documented, but for the purposes of this demo, I didn't want Terraform asking me all the time. Do you want to do this? Yes. Do you want to do this? Yes. I didn't I didn't want so I made a mode where it actually just says go for it, and it does. So That's got added. Uh the sealed secrets are now automated. Uh we as you spin up your very first product and your very first project and you type in that deploy sandbox, it's gonna build the sealed secrets for whatever that target environment is. So when you go to do staging, it'll do the staging ones. It's all hands off and it just works. And it can grab those sealed secrets from various places or generate them

28:06

too. Then we've got GitHub automations now. Uh I don't prior we were doing a little more click ops, you know, going into the console and changing a few things around here and there and getting an environment variable set up in the CI pipeline. That's all been automated with the GitHub command line tool. And we've also also updated Argo C to Argo C D to the latest version of us. So what does this give us? Uh you know, the kind of life before uh GitOps versus the after. Uh no more are we like SSHing into servers. It's git push and we can deploy. Uh no more are we doing a manual Docker Compose up, because that's another popular option if you're using containers locally, you may be using Docker Compose. Well, Compose works maybe great on your laptop, but Compose isn't necessarily a great option for the production environment because you want to be able to release without

28:54

Shelling into a box or running some kind of set of automations there. So no man no manual Docker can put up. We're fully automated and consistent. Uh we really try and get away from the works on my machine. You know, because I had a certain set of libraries, at a certain set of versions, at a certain set of uh you know binaries from certain vendors, mine worked and yours didn't. How many of you have had that magical combination that always works on your machine and no one else's? I've definitely had that. This works everywhere. Containers plus NICs plus all the other opinions that are kind of baked into this piece here, make sure this works everywhere. And now you know who deployed what where. There's no mystery you know get poll and rebuild on a machine for a release. We now can actually follow the audit trail.

29:39

of what changes went into that container, who pushed that container, which you know keeps the person maybe signed off on as part of our our workflow. And we have the ability to work to roll back. We can now roll back with a git revert or go into the GitOps tool and actually just push one button and get a previous version really, really quickly. So it gives us a little bit of breathing room. to get our bug fixed and and get the next version out quickly without having to stress about being downtime or a a a pretty you know hellacious bug sitting out there in your production environment. So if you do want to get your GitOps journey started today, uh there is a one-line installer for Scaff. So if you just go to the uh 6VF org and hit the Scaff repo, there's a one-liner click and paste. And then you just type Scaff my project and it'll ask you some questions.

30:24

First of them being, what kind of a project are you making? We've got two templates currently supported, one being the Django Full Stack app we just showed here. which I'll show you. And then the like a serverless little dummy toy project to see how another template could be created And then we get to uh deployed AWS. It's using the we're using task files under the covers to automate um running all the Terraform for you and targeting the various environments. Now you can just edit YAML, uh change a file, and watch the magic all happen. Uh what you don't need, and I want to also kind of emphasize this, I I am not a Kubernetes expert by any stretch of the imagination. I know all the words I just set up here make me sound like I might be a Kubernetes expert. I am not. But I said at the very beginning of this, we're going to make this uh easy.

31:11

And I that's a word I try to typically avoid. I think all developers have fallen into the trap. of calling something simple or something easy. Uh I really wanted to make something that could go from complex to a sophist sophistic uh sophisticated, fully deployed application very easily. And you don't need a huge team. Uh I don't think I don't believe that Kubernetes and this kind of a style of working is relegated to only large enterprises with teams of, you know, ten to twenty or more developers on staff. I feel I feel that solo developers can benefit from this same level of consistency across all their applications because how often have you come back to an application nine months, eighteen months later, only to have bit rot and thing doesn't fire up again and like you're like, where did I leave off?

31:56

This standardizes all those things across the board for you. So don't let that hold you back. In the presentation there are links to the Scaff repos, some scap project info, the details about the Scaffold full stack template. There is a talk Python uh episode where I got on there and talked for like an hour and a half about Scaff. So if you want a detailed kind of a run through of all this, it's a pretty big stack. Like not only are we deploying Django Postgres, Redis, Next. js frontend. There's also Prometheus for observability, Grafana for reporting and alerting. Uh there 's uh a mail uh server built in there, like mail hog for like local email development. So it's a whole stack of stuff that if you had to spend the time to figure out how to deploy each of these individual pieces onto your own machine

32:46

It would take a lot of time, and here you get it in just one step. Before we go, I do want to show you, yes, that's that's sadness. I'm sorry about that. Um but we do have one up here running. Um fear not. The seventh generation will save us. If I can rem oh good, I'm still logged in. So this this is what Argo looks like. Um it is nice again That's kind of hard to just make a little bit bigger for everybody. You're gonna see all the various applications that Argo is currently managing. Uh and under the covers, you know it's it's managing itself. So you can see here here's the Argo

33:32

app that's been deployed into this cluster. We're using Cert Manager to handle all the SSL certificates for the applications themselves as well. You can see Cloud Native PG operators in here. That gives us the ability to do Postgres replication and backups and all the kinds of fancy stuff with with Postgres. But here's the actual application we deployed, which is the um uh Django Con 7 version of the app. Every piece in here, uh kind of it m the Argo is monitoring the health and monitoring the Git repository and keeping all these things in sync and letting me know when things are getting a little out of whack. So if we saw a new release come in This uses some web sockets behind the covers, but it would actually show you like new stuff being deployed, old pods being spun

34:17

down, new pods being spun up to basically handle that load in real time. But you can see here we've got um Yeah, a back end pod, a front end pod, and a Redis pod all running back here. In production, this may have you know n number of pods running your Django backend. So you can load balance across multiple nodes, for example. This is a single node Kubernetes cluster, that's one of the benefits and strengths of using uh the K3S open source Kubernetes package. I'm not running three servers. to make this all happen. But I'm also probably not deploying this in a production environment. Uh you it wouldn't probably be ready to handle the load of a production environment. But it's great for sandbox and for testing and keeping the the cloud cost down. And so you can see here when things are released. Uh and then the app itself is gonna be

35:05

uh thinking. That's it right there. So that's that's the running. But does have, you know, this is what you get out of the box with Scaff is a Uh this is the Django powered backend from the Django templates itself. And then if you wanted to see This should be the Next. js front end also deployed. There you go. And so this is using GraphQL to talk to the backend Django uh containers that are also running inside this application.

35:54

And if I were to make a change to the code base , I probably can since this one I do have this one saved. And I think I got a couple minutes left, so we can do just one little quick change. Alright, why am I doing it in this? I should uh There we go. This feel easier. Use PyCharm, because it's way easier for me to navigate and use on stage. Oh seven, here we go.

36:42

Open up this project. We'll go into the back end and we'll make a quick change to the template. Um actually if we look at the code. On here we'll try and uh we'll replace the word, you know, scaff powered. How about that? Okay, what am I doing wrong here? Oh you're is it oh cause it's got the link around it.

37:27

You're right. Good call. This should have my Base template in here. Home extends base, of course. Okay. Okay. We'll save that. We will Push that change up.

38:22

Okay. Now, here we go. See there was the uh are you kidding me? It 's because on the other side, so some one thing you have to be aware of is that on the other side of what we're doing right now is that uh The GitOps is making changes and mutating your git repository. So I need to make sure I pull the latest develop back down so that it can actually layer the changes back on top of it and then we can push. Totally expected. Totally expected. All part of the demo. So I could explain that part to you. Okay. Let's go back up here. We'll go to find the 07 repository because we can kind of watch this happen in real time. It'll take a minute.

39:08

Perfect. It'll take a minute to uh build over here, but over in GitHub Actions for this repository, you can see there's my change that triggered the CI pipeline to run. And it's going to run all the uh lint checks, you know, whatever test suite you had running against it. Uh and then it then eventually as it gets to this update manifests, that's where the magic happens and that's when our GitOps is going to notice a change over in the the repository and make that happen. There we go. So it's going to build. The front-end image takes a little longer to build.

39:53

But it's going to keep them kind of linked together. It's like these two versions of the front end and the back end are uh tagged together. And you can see that if we go Into this account. There's a Django 07 backend container repository and the front-end container repository. So as it pushes new images up into that repository, it automatically handles tagging them with the hash of the commit that triggered it and in what environment it's currently in. So it'll move that develop tag. to whatever is pointing to the container that's actually released on an environment. So it's kind of handy because now you can know exactly what's on prod, exactly what's on sandbox, and exactly what's, you know, whatever maybe preview environment you've got going on too.

40:43

Still building. Yeah, that's the only downside. I mean, we made a small change. It still does go through all the tests and all the like machinery to build these containers. So it's important that this is a good reason why you want to make sure you focus on Building slim containers, keeping them as small as possible because that'll speed this process up greatly. We've done a lot of work in here. There we go. Those are done. Update manifests. That is going. Now if I go back over to the Argo CD for 07 and we refresh. We will see, yep. These two are out of sync. So right now it's actually pushing the back end, uh going and grabbing that latest image that it detected. and gonna push out a new back end pod. So you can see here is a split.

41:29

These are the live ones, the one that's got the green heart on it right now. And this one is awaiting a health check to make sure it's good to go. So that's gonna give us again our zero downtime delivery of the of the software. So it's obviously it's not delivered yet because I don't have if I refresh that page I'm not seeing it yet. And then you also get again the whole autolog, you know where when it got pushed, you know, what what changes are in it. Again, I know it's a lot of machinery, but I feel like the uh it's worth this level of structure because most of the time you're not making a single line, single word change. But even if you were. . You can now roll it out instantly with Bill will go back uh

42:15

into a different version of that container. What's also nice is you can see the logs. So you can actually see here there was a there's this is the logs from the Django container itself. So you do get some visibility into the logs on production without having to give access to the uh the Kubernetes configuration file. All right, we've got a back end that's up. There we go. We released some live code. So there we go. I'm excited that part worked. Luckily planning worked out well for me on that one. Okay, and if folks want to talk to me about this, I will be at the six feet up booth out there. I love geeking out on this stuff.

43:01

I get really passionate about good developer practices. I get really passionate about good DevOps practices and this kind of brings both my worlds together. So I love talking about this. Happy to chat about it. You can find me in all these places. Come talk to me. I am a very, very friendly human being, and I do love talking to people too. Uh so again, thank you all for being at DjangoCon and thanks for having me up here as well. And I think that's it. Thank you very much. Oh yeah, we got a question. I think we got a we got a minute. Okay. Hey hit the question outside. Yeah, I think we're good to go. Thank you very much.

Questions this talk answers

What is GitOps and what problems does it solve?

GitOps makes Git the single source of truth for application code, infrastructure, and deployment configuration. Declarative tooling continuously reconciles the real environment with that desired state, reducing manual errors, configuration drift, and unauthorized production changes.

Discussed at 8:44

Why use GitOps for Django deployments?

For Django, GitOps provides repeatable deployments, environment consistency, rollback to a previous image or commit, and an audit trail. It also lets teams promote changes through sandbox, staging, and production without manually operating each environment.

Discussed at 10:14

Why run Django applications on Kubernetes?

Kubernetes provides a programmatic control plane, cloud portability, scaling, zero-downtime rollouts, and consistent containerized environments. Running it locally can expose deployment problems before they reach sandbox or production.

Discussed at 14:06

How can Django deployment secrets be stored securely with GitOps?

The workflow uses sealed secrets that are encrypted before being committed to Git. They can only be decrypted in their target cluster, so passwords and other credentials are not passed around in plaintext and sandbox secrets cannot be used in production.

Discussed at 17:13

How does Argo CD automate Kubernetes deployments?

Argo CD runs in or alongside a Kubernetes cluster, watches Git repositories for manifest or release changes, and applies those changes automatically. It can also sync on demand, roll back to an older container version, and work with Helm, Kustomize, or plain YAML.

Discussed at 17:59

What is Scaff and how does it simplify deploying a Django application?

Scaff is a project scaffolding and automation tool that creates an opinionated full-stack Django setup, including pieces such as PostgreSQL, Redis, a Next.js frontend, Kubernetes configuration, CI, and infrastructure automation. Its goal is to get a usable application deployed on day zero instead of making developers assemble and deploy every component manually.

Discussed at 20:20

What does the developer workflow look like in this GitOps setup?

Developers primarily create pull requests and merge changes into the appropriate branch. GitHub Actions builds and tests the images and updates the manifests, while Argo CD notices the change and deploys the resulting images to the cluster without anyone shelling into a server.

Discussed at 23:27

How does Nix make development environments reproducible across operating systems?

Nix pins project-specific versions of command-line tools and makes the same binaries available to developers on macOS, Linux, or Windows with WSL. Different projects can use different tool versions while remaining reproducible and consistent.

Discussed at 25:46

Note: We understand that names change, people change, and bodies change. We respect each individual's journey and privacy. If you have any concerns about a video or need us to remove content, please don't hesitate to contact us. We will handle your request with care and promptly address any issues.

More videos by Calvin Hendryx-Parker

More videos from DjangoCon US