Peaceful Django Migrations with Efe Öge
Published November 6, 2025
This video features Efe Öge at Django Day Copenhagen 2026 in Copenhagen, Denmark.
Efe Öge - Keeping secrets secret in Django - Django Day 2026
Django Day Copenhagen 2026 talk descriptions: https://2026.djangoday.dk/
Automatically transcribed, so expect mistakes in names and technical terms.
Speaker 1: Welcome on stage, uh Effe. Uh and thank you for traveling and thank you to everyone else for that, madam, who's traveled here uh today. Um great to have you on stage. Uh looking forward to to your talk Um and let's give a big round of applause.
Speaker 2: Thank you, Benjamin. Thank you very much everyone. Um today um we would like to talk about uh keeping secret secret in Django. Um it is this talk started from a uh curiosity actually um It was my secret because I didn't know what the secret key in settings pie is for. And I ignored it for quite long time in my career and I said okay after time maybe I can learn this And I am also using some other frameworks like Fast API and others. And they don't have this secret key in in their settings pie. So what's the deal? Like why do we have it in Django and why we don't have it in the other frameworks? What is this coming from?
Speaker 2: And I hope that we're gonna learn why we have it in Django today. Let me introduce myself. My name is Efeb. I'm originally from Turkey. I'm based in Avstadam right now and I'm working as a software engineer in Nebius. Which is a neo cloud company. And besides that, I try to also pivot my open source projects to some kind of startups, and ESCLOT is one of them. It started as a Django package called Django translate messages and you can use it for your open source projects for free. And I occasionally write uh in my blog uh which is FA. me and you can find these slides there And lastly, I also try to be active in the Django NL community in Netherlands.
Speaker 2: And we're gonna also have Django Girls Amsterdam in the 10th of October this month. And besides that I like playing backgammon run because it comes with age. I'm 30s and I love computers. So this is the agenda of today. Uh what is the secret? I always start I always like starting with definitions and what is the secret key in Django? And the third one is where should secrets live. And fourth one is how who can read this secret? Uh because we don't we don't think that much about where it can go. And what is the secret? Um Donald Trump? No,
Speaker 2: no, it's not it's not political. Uh it is something, a secret is something when we disclosure the value of it. it might give permission grant some kapabilities to other people and it might also weaken our security guarantees. For example, a database password, because most of our applications need to access to a database, and to convince the database that yes, we are coming from the right server, we need to have some kind of common uh decided thing between so therefore they can let us to run queries and change data. Uh or we might would like to charge someone uh in our application and it could be a Stripe
Speaker 2: or any uh payment provider secret key. Or we would like to maybe automatically commit something in our application and we might have GitHub access tokens. Or if you have out uh authentication, we might also have our client secret So these are kinda third party or exten external secrets and as you also know we have Uh Django 's secret key, which is for our internal back-end application. And we also have AWS secret key if you are using AWS. And what is not a secret? Because sometimes I'm also having hard time to understand, okay, should I think my database table name as a secret or not?
Speaker 2: Because if it is known by someone else, maybe it's gonna be easier for them to like penetrate my penetrate but to my database. And the first thing is not secret is configurations. Configurations just decide how our application works. For example, if you have an API-based URL. Or if you would like to say okay this application only runs on uh DjangoDate. dk or time zone of our application. The second category is that the sensitive sensitive information which we shouldn't disclose. So this is actually uh conflict a lot with the secrets Because why? Both of them shouldn't be leak, but they are two different things.
Speaker 2: So what is the example of secret uh sensitive information? A customer data in our database because we don't wanna lose this data. Maybe it it might be about healthcare, it might be about payments. We don't want to leak this data. Or our internal logs. It might show performance problems which we might have in our systems, and attacker might see the pattern and try to uh target us. or financial data. And there are some public values which kinda sound like a uh secret things and we should be careful about them But they are actually public values. They are designed to be shared by others. For example, our odd client ID or
Speaker 2: SSH public key because it's asymmetric way of encryption we need to have public key and private key and public key should be always public. And stripe public key. So, in summary, secrets if we leak a secret, it is gonna disclose your grants of a capability of one action. Okay, this is just like a general uh summary of secrets. If let's go to a bit more like a Django side. I I uh the first thing you notice when you like start start a new project in Django, it creates all the uh a few boilerplate files for you and one of them is secrets. py and in secrets.
Speaker 2: py it is gonna create you a secret key And it starts with the Django insecure because why? You need to pay attention to how to uh ki how to manage this data in your codebase But why? Why do we have this? In Fast API we don't have. Or in other in other some microframex we don't have this secret key. Why do we have it in the Django? Where is this secret key is used? And I read a lot of like Django's code base when I'm preparing for this talk, and it is mainly used for cryptographic signing. Most people say, okay, it's gonna be used for passwords, it's gonna be used for Sessions, yes, it's true, but the main core is actually one thing and everything is using this functionality.
Speaker 2: And cryptographic signing sounds like a bit magical, a bit like fancy term, and I wanted to create a bit scenario analogy to understand it better. And let's say that we receive a message from a stranger person. And we don't know if we don't trust that person that much. And we would like to know that okay, is this message a real message? Like is it authentic message? Is it tempered or not? And but we cannot call the sender and ask, okay, I have this person, he or she says this to me. Can I can I rely on this information? No, I cannot ask this per ask this question to the sender And what could we do for to overcome this problem? And smart
Speaker 2: people thought that okay, what if the sender and the receiver Share something similar between them which is gonna uh enable them to understand if the message is authenticated or not. And I thought a lot about uh analogies which I can explain in this case. There were lots of Alice and Bob keys, signing, sealing and I didn't like any of them and I can I come with another uh example which is sunglasses. So basically I always think that sender and receiver uh share the same sunglasses And if they look at with the same sunglasses, they're gonna see something similar.
Speaker 2: And I try to make it visualize and I came here white plain and I also thought that why not? So actually this is a very real. I came here with the 30 D like middle seat. It's not very comfy. And I'm not very happy with about it and I would like to actually change it to 15A or something like this, so therefore there is gonna be more leg room. I would like to temper the data for sake of myself. So, how does it work basically if we have a like crypto cryptographic signing in this process? So in the desk, uh she's gonna give me the boarding pass with the 30D I didn't like it. Before that, she's gonna put the glasses to this uh
Speaker 2: boarding pass and show some characters. She doesn't need to know the what is this character's uh meaning, but there is gonna there is something deterministic about these sunglasses which is always gonna show same result Then she's gonna put these numbers or like signs under the under the boarding pass and it is gonna give it to me But me, I would like to change my C then I would like to be in the 15A. Okay, I just change this first part in a super nice and unnoticeable way, but I didn't touch to this bottom uh Characters. Then in front of the gate I handed over my boarding pass
Speaker 2: and the same person just put the glasses. Not the same person, different person put the glasses. And they see that actually patterns are not matching. And they say that okay, there is something synicky in here. And If you would like to match this analogy to technical terms, my boarding pass is actually a value, which is or a message. Should I trust this message or not? And special glasses is basically an algorithm which is fed by uh with my secret key. So therefore when we have different Django applications Our encryptions are not gonna be the same because our keys are gonna be different, therefore uh the the encrypt uh the signed values are gonna be different.
Speaker 2: And the figure seen on sunglasses called signature and you might notice the aesthetics next to it because I think this is not a right term, especially for me, because for human signatures, mostly we have the same signature for everything and we are just repeating it. Maybe we have small differences But it is may mainly a same thing. But in cryptographic world a signature is actually a unique thing for what you signed for. So therefore it it is different than the human signature. Uh i it made me a while to understand why it's called signature, why it's a bit different. So please think that it is a bit different than the human signature and uh elec uh electron cryptographic signature.
Speaker 2: And looking again with same glosses is just a verification and change seed number called a tempered value. Okay, this is enough with the analogy. Let's come back to code, and I would like to show some Django code to you. And Django cryptographic signing actually relies on uh stays in the Django core and you can just import like this And on third line you are initiating a signer and you just would like to pass the value you would like to sign with the sign method. And Django signs this value and shows the uh shows the output in here in the print statement And as you notice that
Speaker 2: when we sign the value, we actually didn't hide the value which we had. It is already like visible to anyone. It's not the encryption because most people Uh or sometimes you might uh tend to confuse with encryption and uh sign crypto cryp cryptographic signing And when we have an encryption we don't see the value which we encrypted, but when we assign a value we see the value, but we would like to be sure about authenticity of the value. And you can also call unsign function to uh check that is it really authentic or not. And let's say let's try to also mimic the tampering which I did in the cartoons
Speaker 2: I sign the value and this is the assigned value starts with 30D and I just wanted to replace my seed 30D with 15A Then I kept in the tempered variable. And I would like to unsign this. Django is automatically gonna raise me an exception which is a bad signature because it is not the same value which I passed. Okay, FL like you mentioned about secret key. Why do we have it? And in here we don't see any secret key. Like where is it coming from? So to do that we need to go to the source code of Django and in Django code signing when we are initiating a signer, we are passing a key And if you don't pass
Speaker 2: uh a specific key, Django fallbacks to the it's it is uh secret secret key. Uh and when we are signing the value In here we are appending the signature and signature is actually created with the self dot key I know it's also kind of a bit like a matrushka, but actually we are using a secret key inside of signing And in Django we have different type of signers. In the examples you So mostly about the most primitive one which gets only the string and don't know about
Speaker 2: when do we sign this value And in the second one, we use the same class, but we are using a different method, which is SignObject. Which basically do we if we have a JSON serializable Python object Django under the root serializes this object to a JSON string, then it calls the same sign method. But if we would like to do a more time sensitive thing like uh if you would like to send the email and it's and in this email we have a forget password link and it should be only valid for 24 hours. Then it became more time sensitive information. And in that case, we can use time step signer. And it also gets all
Speaker 2: input and adds a timestamp And in the last one, you can pass Python objects to the signing dumps. And it is also uh adds timestamp. Okay, up to so far I mostly uh talked about crypto fics uh signing and I said Secret key is only used in Django for this, but where do we use this crypto for crypto cryptographic signing in Django And these are the applications of cryptographic assigning in Django. If we so there are different types of um session backends in Django. And if you use sign cookie session, this is the default one, so all the data of session are hold
Speaker 2: on the browser. And as a Django we just need to verify that okay, is it tampered or not by our Our secret key and we are using the signing functions of Django under the foot. And same as in the second one If you use Django's default class-based views for password reset, they are also using time step signers. Or session authentication hash, it is also binding the users uh validity or if you are I don't know it is this is a very nice feature of Django which is called messages framework in Django admin it is also very handy to use uh to notify or st to show notification pop-up user and it also uses uh this signing to be sure that these messages are not tampered.
Speaker 2: So actually, cryptographic signing is a method to store less and verify more. Uh if you come back to the forget password example, we could actually just could generate a random string and keep this value in our database. And when someone calls the endpoint, we can just check that okay is this value matches with our database value. If it's not, we can just raise an uh like raise an exception or return 400 response But we need to create more database fields for everything like forget password or some other cases. So there is gonna be maybe overhead in your database and you would like to limit the overhead. in your database. Like in the example you you might remember that
Speaker 2: I don't wanna call the sender to verify that is it really the that message or not. So in in in the real world of Django it corresponds to the database queries. which we make. Okay, I mentioned enough about uh w cryptographic signing, why do we need a secret key? But I never mentioned uh about how we need to uh generate a uh secure uh secret key. Because the default one is insecure when you create your first Django application. And I wanted to have a small quiz in here. So we have three options. I have to just close my eyes and press buttons and I hope that it's gonna be okay.
Speaker 2: Or I'm gonna do a bit like fancy stuff, I'm gonna hash something. Why not timestamp? There is enough entropy there Or I'm gonna use uh uh online Django secret key generator. How do you feel like A? Who says A B HD this is the fan. I like this one also. And C. Please don't do there are lots of websites. I checked before presentation, like preparing this presentation. Maybe there are 10 different web pages. uh who try to say us that okay this is only on your browser we don't get your like secret we don't need it because why Django already has the solution built in, so uh there is a specific method for this.
Speaker 2: Uh you can just uh call this method in your Django shell. Uh And it's gonna return you long enough uh secret key And this is another quiz. Now you know how to create a secure uh Django secret key. Maybe you had a bit weak ones, uh, you would like to change it right now. What is gonna happen? Like on like in for example, Monday you change the secret key, you follow the best practices, you follow the method. What's gonna happen? A. Nothing, because the secret key doesn't store any value in our databases, so everything should work smoothly.
Speaker 2: B all sign values keep working until they expire. C Zengo automatically re-signs everything and and it's gonna work with new secret key or all signatures can no longer be verified. Who says A? B, C, D, yes, D So this is not a peaceful peaceful way to follow best practice because if if you do that a product manager is gonna come okay I felt like you did the nice thing you did the right thing but it wasn't that nice for our customers But can there be any other way? And Django has solutions for the problems opposite to the other technologies which we have.
Speaker 2: So this is something I like about Django. And in Django we have a actually another setting called uh secret key fallbacks. And basically what we're gonna do, we're gonna Move to our old secret key to secret key full fallbacks and we're gonna create a new secret key and use it as a secret key. And how it's gonna work under the hood when we are signing new values We're gonna use the new secret key and when we would like to check the we would like to verify the old secret key. We're gonna start from new If it's not work, okay, we're gonna try with the fallbacks. If all of them are failed, then we're gonna fail. Okay, this is at hampered value So now we saw okay how the secrets work in Django.
Speaker 2: But should I just commit these secrets to my Git 's repository? Some people say that this is not the best practice, but why? So this is the this is the convenient list, this is the happy list, like okay, just push it, push. Like why? Who I only have the repository, maybe some intern is gonna have access, but they're gonna have it for limited time and they're gonna I'm gonna remove them. When they have access to this, they're gonna have access to this. And you cannot change this history of kit and And your codebase is designed to distribute, not to distribute, to access your production databases. They they are like developers are there to contribute code to you.
Speaker 2: And usually what people do, okay, let's use environment variables. And there is an environment package, or we can just directly get from here And I'm gonna set each uh secret as an environment variable and I'm gonna use them directly. And I'm gonna use curly braces, curly braces instead of get, so therefore if I'm missing any of them Uh deployment is gonna fail, I'm gonna get alerted. It is nice. But once secrets became as many, we have secret key, we have database password, we have stripe secret key We have a lot. And there's gonna be even more. And we have different environments too. Like we have development
Speaker 2: environment, we have CICD environment. We need to also have secrets, different secrets for them. Staging, if you're lucky, not everyone has staging environment. Production and Not every circuit has to be provided wherever the application runs. It's it's it became overhead in your head And this is some kind of imagine like it became about a matrix, you have lots of secrets to manage. And if one of them is missing, you're It's gonna or maybe if one of them has a typo it's gonna be very hard to understand because there's gonna be a customer who's gonna complain about it because you don't you can it's it's very hard to write tests for your secrets also Uh what
Speaker 2: if we had only one? Like it all the bad things start like this, but I think it's gonna end a good way. It's not like a ring. Uh let's create one uh root encryption key per our environments because we don't want to use the same key to different environments, then it's gonna be actually reduce our secur uh uh Reduce our uh security best practices. Then encrypt each secret key with the environment rule secret, which is a symmetric encryption, like in Python it's called like FairNet encryption And commit the encrypted value to our codebase. So therefore we can always have match with in our codebase and we we are not gonna deal with lots of burden of uh different script keys.
Speaker 2: And you're gonna only have one must root key for environment. And with this idea, uh, this Django root script package is created. Uh and it's an open source package, you can use it. And how does it work? Uh since we are in Django, we have a new uh Django management command which is called uh generate root encryption key and you can pass the uh environments we are which you are creating a secret key for. And it is creating a dot env file for you and it automatically adds this file to your gitignore. So therefore you are sure that you are not gonna commit this root script key. Then when you like to encrypt your values, you can also use another uh management command which is called encrypt secret
Speaker 2: and dash dash uh your environment. and it's gonna prompt you which secret you would like to encrypt and you can pass uh the plain text and you're gonna get the encrypted version Then in your settings you can just call a simple function which is called getSecret and you're gonna pass this encrypted value there. And when uh on the runtime of your application it is gonna one time uh decrypt it So encrypted values travel with the codes, only the root key must be pro uh provided separately, maybe from your CI CD pipeline or a different way to do it. But we didn't eliminate the secret key management. We still need to manage our secrets, but we reduced what has to be distributed.
Speaker 2: So instead of 30 items you're gonna manage maybe three So we are done with the where should secrets live. Now the next item is who can read the secrets of our application. So our Django can read it, our CED reverkees can read it, our CI CD can read it because they also have the data. And deployment platforms, developers, dependencies of our like third-party packages which we install and anything we add to our installed apps. They have settings and they can just make it uh like they can call settings any value and they can use our secret values or logs error reporting coding agents or LLMs
Speaker 2: Every reader became part of the trust boundary in here. So therefore we should think about each time when we are adding a complexity in our projects, we are actually maybe Possibility to leak our secrets Okay, this is interesting. And secrets also travel, like it starts with dot env file you are uh adding to your production project. Then Django has it, Django lost it is memory. Then when you have an error, you might have it in your traceback. So therefore it's very important to have debug faults on your production environment
Speaker 2: Then if you copy paste your traceback to somewhere else, maybe your friend, or you would like to troubleshoot with LLMs, then It is even more. So most leaks don't require super quant like post-quantum computing. Most of the time it happens via small mistakes you did to make something a bit fast. And what if the secret leak? Maybe it's gonna happen, maybe it's not gonna, but there are some precautions which we can do before this happens to you. So the first thing is that limiting the capability of your secret.
Speaker 2: So if you would like to create a secret key for your AWS account. because you need to put some uh files to S3 or maybe you're gonna do some other things don't have admin user as a AWS user and have this because If this is leaks, there is gonna be the blast radius of this uh leak is gonna be even bigger. For example, a database credentials shouldn't be a super user Or an APA credential should only have the scope of the apps we are using. And make replacement routine like If you have you know how to rotate your secret key. Try to to plan it in every one year or six months depending on your schedule.
Speaker 2: And avoid long-lived secrets. Like if you have AWS, it is also possible to have uh more I am rolled uh based uh permissions then like if you don't have any secret to hide It is not a problem. You can create this short-term uh secrets on the runtime And that's all like is uh is a is a summary of what happens what if a script leaks and And if I would like to have a checklist, is it really a check is it really a secret value before encrypting it think about it? Does it only have a capability which we need? Was it generated secretly or from a somewhere from
Speaker 2: the cloud? Does it need to be long-lived? Maybe it can be a bit short-term. Where does it really live and who can read it? And can I replace it? Can I rotate it in some uh periodical and if it's gonna happen did I set up the schedule of it? And thank you very much for your time and my presentation was this. And if you have any questions, I'm also happy to answer them if you have time. Otherwise, you can also find me on the hall.
Speaker 1: Thank you. So we have a bit of time for questions and obviously security. So uh
Speaker 2: Yeah tough ones on the hallway uh is the ones in here. Exactly.
Speaker 1: Alright. Uh two in the back I see Do we have the microphone for them? Oh
Speaker 2: this is such a nice movie by the way. This is an inside joke. Please watch it. It's called Daylive if you haven't watched it.
Speaker 3: Yeah. Oh. Well, thank you for your talk first. Loved all the you you had it so organized. Amazing. Um but you have a lot of the you have a list with old keys. Um when do you get rid of the old keys uh from from the list? Like I suppose you have to get rid of them at some point.
Speaker 2: And Marica you you are mentioning to do like Django Secret old keys or
Speaker 3: Yeah the one yeah where you If if it doesn't match the current key, you fall back to the older keys and when do they when do you remove them from the list?
Speaker 2: So the the mo the biggest bottleneck in here is m times uh time stop timestamp signer related uh signed values. So depending on your application logic and I I can read I can read the source code and say okay Most of our uh signatures should expire after 10 days, for example. Then I would like to drop the old key after I change the key, maybe like adding a bit of buffer maybe 15 days later.
Speaker 3: Okay, thank you.
Speaker 4: Uh, thank you for your talk. Uh actually I was wondering uh how to deal with uh compromising for uh one do one of the keys. Secret key for uh for example. You know, if this got leaked for some reason on production this means you know the the whole system uh got uh uh compromised so changing or rotating the Secret key is the solution to overcome, but this is will come up with you know uh some signing uh will be broked. Uh I don't know. What do you recommend to deal with such uh things.
Speaker 2: You are mentioning to the if my like screen key is leaked, yeah. What should I do the first day?
Speaker 4: Yeah.
Speaker 2: I think the first thing we should do is just rotating the secret key without using the uh fallback methods because what I can do I can use like forget password flow to get my admin users and I can do lots of things. And so this is what I would suggest instead of just People can uh log out next day. Uh it's okay.
Speaker 4: Security
Speaker 2: is more important in my opinion. Thank you.
Speaker 5: Hey, thank you for the presentation.
Speaker 2: Thank you, but
Speaker 5: I got a couple questions. I'll try to make them uh real quick. The first one is um do you know when it's suggested to roll the secret key?
Speaker 2: I don't know to be honest personally. Yeah.
Speaker 5: Okay. And the second one is because I I always feel nervous about having uh in my repository um keys. Because if the repository leaks, for some reason I have something else leaking that can be decrypted in the future. And I know I can roll the secret, but I'd like to avoid it. Um is there any workflow you suggest uh that can keep this outside of the repository?
Speaker 2: There are also some secret managers like cloud secret managers which we can use. And they like I mentioned enough AWS, but I don't know, there are other the tools too, or secret vaults and They are keeping the they are they even don't keep the encrypted value in your code base.
Speaker 5: Kubernetes secret or something in another directory and you can read it from there.
Speaker 2: I think this is also definitely a possible way to do it in a bit like higher level of like abstraction in your like uh Docker or like Kubernetes setups also
Speaker 5: Thank you. Thank you for the time.
Speaker 2: Thank you.
Speaker 1: Um you had a slide with the name of your uh of your project uh on. Just wanna re refresh uh uh my own and everyone's memory of what that project was called so we can uh
Speaker 2: uh
Speaker 1: pip pip install
Speaker 2: Django root uh secrets and I'm also gonna put it's gonna take some time. I'm gonna put it to the Zulip and or yeah I'm gonna also
Speaker 6: We have a question more for the audience
Speaker 1: Yeah, we're a little bit over time. Uh let's do it. Let's do it.
Speaker 7: Okay. Thank you for your talk. Uh interesting points on a very important topic. I'm a little skeptical about the one master password to rule them all approach. Am I understanding it right that you if if you commit these That means you use the same secrets in all environments? Or am I misunderstanding something? Like is your century secret the same in in in staging as in production?
Speaker 2: No. We have different uh root keys for different environments.
Speaker 7: Right.
Speaker 2: So per uh I suggest to have per environments root secret key And but we are using the same root key for the all keys which you had which we have in that environment. For example, in production. If we have a secret key called A, we are using this A key to encrypt all production secret keys.
Speaker 7: I think I'll catch you in the hallway and get on the book.
Speaker 2: But by the way, this is definitely a trade-off. Uh kinda I try to to like promote having a less key. to prevent more human errors which we can pass copy paste like environment variables. But I I totally agree with that too. Thank you.
Speaker 1: Yeah.
Speaker 7: Thank you.
Speaker 1: Ife, thank you so much for the wonderful talk.
Speaker 2: Thank you.
Speaker 1: And we have uh last talk before the break.
October 2, 2026
Copenhagen, Denmark
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.
Published October 13, 2026
Published October 13, 2026
Published October 13, 2026
Published October 13, 2026
Published October 13, 2026
Published October 13, 2026