 I'm going to get started right on time here because I always run long, so I want to squeeze as much into this time as possible. So hopefully you're here to hear about advanced configuration management in Drupal 8. First I have to apologize. This is an intermediate session, so I'm assuming some knowledge of configuration management, but there is actually a beginner's configuration management session tomorrow, so kind of the wrong order. So maybe even if you're a beginner, sit through it, try to absorb it, go to the beginner one tomorrow, and then maybe you can go back in time and remember this one, and you'll have the full thing. Otherwise, watch the videos online. So anyways, if stuff does kind of go over and you're like, what is he talking about? There's a session tomorrow. Go to it. It's going to be a good one. We've already talked. So I'm Mike Potter. I'm the Prime Maintainer of the Features module that some of you might have used. Also the architect of the Open Atrium 2 distribution in Drupal 7, so I've been doing Drupal for a long time now. This is my 10th Drupal con. And what I want to talk about today was a lot of topics around configuration management, but not just the basic how you do it, but what problems are people having. And if you're at the Drees note this morning, you heard Drees mention that one of the problems people are having with Drupal 8 is still configuration management. Even though it's great and it works pretty well, we want to have some tweaks to it. And so I'm going to talk about some of these things and how you do it today, and knowing that some of these things are probably going to be addressed in the future by this CMI2 initiative. But this is more of a real world, for people actually building Drupal 8 sites, what problems do you actually run into in building really large Drupal sites around configuration management and how do you solve some of those. So we're going to go really briefly through the core workflow, then we're going to get into environment specific config, we're going to talk about how you can install sites using config, we're going to talk about how you override config, going to talk a little bit about features, some other topics like templates and some other miscellaneous topics there at the end. All right, good. So let's do a really quick review of config workflow in Drupal 8 core. So in Drupal 8 core, the first thing you do, and here I'm talking about, you know, not necessarily what you do that Drupal tells you to do, but what you do on a real site. So hopefully all of you are building real sites. This is probably your first step, which is the whole idea of config management is you want to treat config as code, so you've got to get your config into your code repository. So you're going to go into your settings.php file and you're going to tell Drupal where do you want the config to be stored. Because by default, Drupal is going to put that in your files directory, and your files directory is probably not something that you're checking into your Git repo, right? So you've got to get it out of your files directory, put it somewhere else, doesn't really matter where you put it, I like to stick it in just a top level directory called config, config slash default. If you're on hosting where you need to put it one level above that, feel free, it's your choice here. But just someplace that you can then add to your Git repository so that changes to that directory will get committed. So make sure it's in your Git repo. So then what happens is on your development machine, when you do, and I'm going to show a lot of examples for Drush here, and if you're a Drupal console user there are similar commands, I just didn't go through an update on my slides to put two things on every slide. But if you're using Drush, and we're going to be doing stuff on the command line, rather than through the UI here, you say config export, and that's going to take all of the config from your database, and it's going to write it as files, as YAML files, into that sync directory that you just set up. And now you push that to your Git repo, and you go over to your, you know, make sure everything's looking good, you review your changes, go ahead and push that up. And now you go on to your QA server, and you do config import, and it's going to take that same directory, which you've just pulled from your Git repo, and it's going to load that config into your database. And so now you've just moved your config from dev to stage, and you do the same thing from stage to prod. So basically you're going to run config export. So config export in Drush has a couple other options to it. Feel free to do a dash dash help and see the details on it. Specifically you can give it an argument, which is the label. It defaults to default, so that config slash default directory when we set it up in our settings dot PHP, you can set up additional directories if you want, and then use that key that you give in settings dot PHP as the label. So for advanced things, you might have maybe more than one config sync directory. You can do it this way. For example, some people like to have on their production environments maybe a read-only config directory, and then a read-write config directory, and so you can import from one export to the other, that kind of stuff. There are a lot of options on the Drush command for doing Git-like stuff. There's add, commit, and push. My personal opinion is just learn Git and use Git. I don't try to force everything into one giant Drush command. I kind of want to control my Git and know what it's doing a little bit more. So I don't use those, but if you're comfortable with those, go ahead. Then there's the config import command, takes the same label, a couple interesting flags on this one. If you actually want to see what's about to be changed, normally when you do a config import, it will give you a list of things that are going to be changed, and you type yes or no as to whether you want to import that or not. Sometimes you really want to know, well, what change am I about to blow away? Like what's really going to change? So you can do the dash, dash preview diff, and it will actually show you a diff of the config changes. So you can say, oh, hey, when I do this config import, it's going to change my site name or whatever it is. So that's a really useful command. Another command I've seen people or another option I've seen people use is dash, dash partial. So be very careful. What dash, dash, partial does is it will import config, but if a file is missing, config import's normally going to delete that config. If you do dash, dash partial, it won't delete the config. So I've seen some developers use this because they think it's somehow safer. Like, oh, I just created a content type, and I need to pull my other devs code, and I need to import it, and I don't want to lose that content type that I'm in the middle of working on, because when you do a config import, it's going to blow away your entire config database, right? So they'll do a dash, dash partial so it doesn't remove their stuff. And the problem with doing that is now you're that same dev, and now you say, okay, I've done my little hotfix, I'm going to do a config export. Well, now you've not only exported your hotfix, but you just exported that content type you were in the middle of working on that maybe isn't done yet. And so if you're not careful with that next git commit, you might just be committing code to your fellow devs that isn't ready yet or is broken or something like that. So if you do this, don't automatically do a git at all, review your changes. And this is just general good git maintenance anyway, right, before you do a push, review your changes. So the one useful thing for partial, however, is sometimes you've got config and a single module that you want to import. A really great case for this is if you're playing with the migrate module and you're doing data migrations, migrate module is all driven by a bunch of YAML config files. So as you're debugging your migration, you're going through and you're tweaking things, but just changing the file in your migrate module isn't going to do anything. You've got to get that loaded into the database before the migrate module is going to do it. So here you can say dash dash partial, dash dash source equals, and then the path to your modules config install directory, and then that will read that config and update it. So that might be your migrate module config, for example. So that's the one use for partial where you don't want it deleting things, you just want it kind of overriding stuff. If you're using features, this is kind of the equivalent of doing a feature revert of one specific module. Okay, so that's basic config workflow. The headaches that are caused by config, and the reason why we still are talking about config is you run into some problems sometimes. So the first thing to remember, and I think even in the intro talk, they talk about this, config management in Drupal, the config import, config export, it only works if your site IDs are identical. So if I'm on a website, if I'm on a Drupal site and I do a config export, and I send that Git repo to you, and you do a poll, and you try to import it, it's going to fail unless your Drupal site ID is the same as mine. The site ID is actually a piece of config itself. It's something that is set up when you install Drupal for the first time. If you and I have installed Drupal separately, we're going to have two different UUIDs, and we aren't going to be able to share config. So that can be a problem. We'll talk about how to fix that a little later. Another problem is when you actually create config, when you initially import config, especially from a feature, if that config.yaml file doesn't already have a UUID in it, then Drupal is going to create one randomly for you. When you export something with features, features are stripping out the UUID. So if I send you a module that has config in it, and you do an install of that module, you're going to get that content type or fields or whatever is in that config. If your other developer then installs that same module, they'll get the same config, but they'll have separate UUIDs. And now when you start exporting and importing each other's config, what you'll find is it won't fail, like the case of the site ID. It's just always recreating it with different IDs. And then when you export, it wants to change it. And so you're just always getting these changes in your Git repo that our UUID changes. So it's useful to be able to have the UUID in the config so you all have consistent ones. The other thing that causes people trouble the first time they start using config management is this whole idea that config import will actually delete stuff. So if you delete a file, delete a content config file out of your config sync directory, when you do a config import, it's going to delete that content type or it's going to try to. It will actually complain if you have content that exists. So if you've already created blog content and you delete the blog content type file, it's actually going to give you an exception that won't actually delete that for you. Fields, however, will actually go ahead and delete. Field storages will delete, leave orphan content behind in the database. This can actually be good and bad sometimes, like if you're trying to change something in the field storage like the cardinality, you actually can delete that field storage and change the cardinality and restore the config and everything works and your content's all still there and it's all hunky-dory. Sometimes it's useful that it doesn't warn you and that it actually retains content, but just keep in mind you can actually delete stuff this way. So how do we fix some of this stuff? Let's first talk about the first big reason why we're probably here, which is how do we handle environment specific config? And Dries talked about this in the keynote a little bit. But this comes up whenever you're doing a large Drupal site that has multiple environments like your local dev, your stage, and your prod. You've got different configuration. And so you might have one thing enabled on your production server, but like Dries said this morning, you don't want to send emails to all your users. You probably don't want to have your Google Analytics key on your dev environment because now you're polluting the client's Google Analytics page with your own testing, lots of things like that. So there's this great module called config split, written by Fabian Bircher, and it lets you split the config into different sync directories. So when you do it, and it ties into the normal import-export mechanism. So what we're going to talk about here is how this works. So what you first do is you create a sync directory for each of those environments. So you have normally the config default directory, which Drupal uses. Now you're going to create like a config dev, a config stage, a config prod, like whatever number of environments you have. And you can have as many environments as you want. After you've created the directories, you go into the config split UI, you enable the module, and you create what's called, you create a split for each one of those directories, so you create a dev split and a stage split and a prod split. Make sure that they're all disabled by default. So by default, there's no active splits. And then you export your full configuration, just like normal. And now in your settings.php file, you're going to tell config split what environment you're on. So you're going to enable one of these splits. So somehow, some way, you need to figure out what environment you're on. So a lot of hosting companies will have like an environment variable you can check. If you really have to, you can check like the host name or something like that. But somehow, some way, you need to figure out what environment you're on and enable that split. Then when you do the config import, it imports the normal default directory. But it also will import the config from the split, and it will merge the two together. So you'll get all your default. And then if you're on the prod environment, you'll get the prod config. If you're on the local environment, you'll get your local config. But it just ties into the whole import-export mechanism. So if you're already used to using config import and config export, this becomes really seamless. Once you set it up, it just works, and it's great. If you have to export just the config that goes into the split, so like let's say you're using the develop module on your local dev server, you can say config split export, and it will just export that develop config. It won't touch your config default directory. So let's do this a little visually for people that want to see a picture. So you've got your dev environment. You do a config import. That config import is going to take your default directory, your default Drupal config. And it's going to look in the local directory, and it's going to merge those two, put that in the database. So now your develop module is turned on, everything else. Now you export that config. It only is exporting the stuff to the config default directory. But if you've changed like the site name or something, you'll get that change. Now you go over to your QA or staging server. You do a config import. It's going to take that new updated default config, but now it's going to merge in whatever is in the config stage directory. And that might be the solar server configuration for your staging server or something like that. And now you could export that. It exports back to the config default. And then on your production server, it's merging the default with the production. So as you go through, it's just merging what is needed for each individual split. So the config split has a couple concepts that take a little, it's kind of jargony, it takes a little getting used to the first time. They're trying to start to change the kind of UI and definitions here, so this is kind of in flex. But traditionally, it's had something called a black list and a gray list, and it gets confusing. So a black list, depending on how you think of it, it's actually a white list, but it's called a black list. But it's basically, it's the module or config that you only want in the split. So if you want to install the develop module on your dev environment, you put develop in the black list, even though you want it enabled on development. So like I said, terminology is a little weird. So when it exports the config, the config doesn't actually even exist in the default directory. There is no develop config in the default directory. It only exists in the split that you export it to. The trick here also is config split will automatically enable the module for you. Don't mess around with the core extensions config. Don't try to get over smart and say, I'm going to put core extensions in my split and change it here and change it here. The config split module handles module enabling for you. So if it's in the black list, config split will enable it when that split is imported. So don't mess with core extensions. In fact, if you black list, this is why it's called a black list. If you put it in the black list, the reason it's called that is it's actually removing it from core extensions. So if you look at the core extensions that gets exported to the default directory, it won't have the develop module in it, right? So it's been blacklisted from the default. So then what's the gray list? So the gray list is config that exists in both places. It has config in the default directory and it has the same config or different config in the split directory. And so what happens when you do the import is if you have config in your split directory, it overrides what's in the default directory. So if I have site settings in both places with different site names, whatever site name is in my split directory will take effect. So it's in both places. And if the split exists, then it's overridden. It also won't delete it when it's exported. So if it's in the gray list, then you will always get a YAML file. It will put it in the default directory and it won't actually delete the config. And it will only export that config if it's different. So if I don't change my site name, it just exports it to the default directory. If I change my site name and I'm in a local environment, it's going to export that difference to the local settings, to the local sync directory. So let's look at a real example. So there was a lot of complex words there. Let's look at something real here. And we've kind of talked about a little bit this. Let's say, OK, on dev, we want to develop a module. Like, that's pretty common. We probably all do this. We've got a complicated server setup. So we're doing solar searching of some sort. So we've got a solar config. We're not going to use the client's production solar server for our little dev environment because we probably don't have all their content on our local environment. We just got our own stuff. And we don't want changes we make locally to get pushed to their solar servers. We've got our own config. And let's say we change the site name to dev because we really want to know when we're working on it that we're not messing with production, we're working on our dev server. So we've got a different site name. And then on our staging QA server, we're going to do some other things. Maybe we've got the shield module here because we're enabling the QA servers in the client's environment. We don't necessarily want everyone in the client's organization to be looking at our new server yet because they haven't launched it. So we're going to put the shield module on there to kind of password protect the site. So we've got a username password config. And they've got their own solar server for testing on the stage QA server. And then on production, we don't have the shield module. We want it to be available to everybody. And now we're using the production solar configuration. So lots of configuration changes, right? And with core config management, you couldn't do any of this. You need config split for it. So here's the config split UI. And I know you can't read, especially with all the glare. You can't read probably any of this. But I did want to step you through it. Feel free to watch the video afterwards and zoom in and do whatever you need to do. But I did take a screenshot of what the dev split looks like. So the first thing is the label, which is just your machine name called dev. Then it wants to know what folder you're putting it into. So you can, again, use whatever folder name you want. I usually use config slash the name of my split. So in this case, it's config slash dev. Notice that the active flag is not enabled. So you leave these disabled in the UI because you're going to enable it through settings.php. Then the next comes the blacklist, which they now have renamed in the UI. It's called the complete split. And I'm not sure that's any better, but at least it's different. And it will say down there in really fine print at the very bottom, it says the complete split slash blacklist listed here will be removed from the sync directory. And so it actually explains, if you just read the screen, which I know some of us don't do sometimes, it actually explains everything it's doing. The UI is actually very nicely verbose if you read it. And what we're doing here is we're saying, we want the module devel to be enabled in this split. So we stick it in the modules list. But then we have special config. We have our solar server. So you have to figure out what the name of your solar configuration is. In this case, it's search underscore API dot server using the search API module, whatever your solar server is. So we want that configuration to be active for this split. And we're going to have a different file for each environment. And then if you keep scrolling on the UI, these are all one page. I'm just splitting it onto pages so we can read it, but it's one long page. So then we have the gray list, which is now called conditional split. And in the gray list, we have a different site name. Site name exists whether this split is on or not. So here, this is the case of the gray list. We're just going to override the site name with the dev site name. And then down there, we tell it to only split when it's different. So when you go ahead and do your config import or config export, here's the kind of directory structure you get. So when your config default directory, that's the big, long, huge directory that has everything in it. So there's a lot of dot, dot, dots, but you'll see that system.site is in there. That has your default site name. And then in the dev split, you've got whatever config the develop module needs. Then you've got your solar server config. Your solar server config does not exist in the default directory. It only exists in these split directories because it's specifically marked in the black list. And then system.site, that's where your overwritten site name for develias. And then on your stage server, you've got its solar API, search API, solar server config, and then you've got the shield settings that have your username and password. And then for production, finally you just have the solar server for production. So you'll notice that the search API file names are the same for each one, but if you looked in each of those files and you looked at the YAML files, you know, one's gonna have the host name for your local servers for solar, one's gonna have your staging solar, one's gonna have your production solar. So the contents of those files are different. And when you do a config import, it's just gonna merge whatever it needs. So you'll notice that core extensions doesn't show up in any of the splits. A core extension is still in your default directory. Your system site's gray listed, so it shows up in those two places. Your devel is just in dev. Your stage is just, or your shield is just in stage. And your search API solar config is in all three. Okay, so that's config split. So hopefully that makes sense. I'll take questions at the end because I wanna kinda get done, but I'm happy to answer questions at the end. Okay, so let's switch gears. So that tells you how to do environment-specific stuff. And by the way, this can be taken amazingly far. You can have more than one split enabled. So I gave you the simple case of environment, right? You're not gonna have more than one environment enabled at a time. But you can have other splits. For example, when we did the Weight Watcher site, they had an interesting situation where it's a multilingual site, but they wanted multi-site by country. Countries have more than one language, right? So for Canada, for example, they needed the English and French enabled. So they created split directories for each language. And so if you're on the Canada site, they enable both the English and the French with config split. Sorry for my cough. Okay, let's talk about installing from config. So one thing that's really useful to be able to do on projects with lots of developers is all install the same site with the same UUID. Like we talked about, if I do an install and you do an install, we're gonna have non-matching UUIDs and we can't import and export. So there's been a couple of ways to do this. The way I'm gonna talk about here is using something called the config installer profile. So the config installer profile you can get from Drupal.org, you can get it with Composer. Basically what you do is you go, make sure your config sync is in your settings.php, which it should be already anyway. And then via the UI, you can do a normal Drupal install and it will prompt you for either the location of that config sync directory or for a tar ball that contains, you know, a tar version of that config sync directory. If you're doing Drush and you do a site install via the site install command and you give it config installer as the profile name, it will install using the location that you gave it for the config sync directory there. So what does this do? This installs Drupal and then it automatically does a config import of the config sync directory. So when you're done, what you have is whatever site you exported. So whatever site, you know, you work on your site, you get it all working, you create all your content types, you create all your fields, you do a config export, it's in your Git repo, you take that config sync directory and you install it using the config installer profile. When this is done, you'll now have a clean Drupal site with no content but all of your config. So you'll have all your content types, all your fields, all your views, everything else there. The way it does this is really clean. It ensures that your site UUID matches whatever was in the config export directory. So you don't get a new random ID, you get the one that was in your sync directory. So if you do a config install with this and I do a config install with this, we both now have matching site IDs and we have matching config IDs. It also actually works properly with if you're installing your own profile, your profile name is a piece of config. It's in the system sites config directory. So let's say I'm installing, I don't know, OpenHRM which doesn't exist in D8 I know that it's my favorite profile. When I'm done with config installer and I go look at what profile my site's using, it no longer says that it's using config installer, it now says that it's using atrium or lightning is probably a better example. If you install a lightning site with this, when you're done, it will actually say that your profile's lightning, not config installer. In any configuration that profile installed would be installed now too. So it looks just like you've got a clone of whatever that site was. So it's a really clean and easy way now to clone sites from config. This is something else that you're probably gonna see moving up to core very soon. So there's the issue or there's the project URL. Now there was a way to do this before I talked about this when I gave this talk a little bit last summer before the config installer project was really ready. So I know some people are still doing this. There's basically if you have your own custom profile, if you've created a profile for the client in your profile's info file, you can add a key called config install, give it the path to your config sync directory, and then with this patch that I linked down here to Drupal 8, you can then do a Drush site install of that custom profile name. So if I'm building a site for like the MBA or something and I have an MBA profile, I can say Drush site install MBA profile, and with that patch it will go load the config from that config sync directory. This is the issue where kind of a lot of the work that went into config installer was done. This is I think pretty much deprecated now that config installer is working well. But this will also ensure that your site UUIDs are the same. Because the problem is if you just do, if you like install standard or install minimal and then do a config import, that's not gonna work because your site ID is not gonna be set properly and any config created by the profile is not gonna get created properly. The other thing I've seen people do is there's a Drush option called dash dash config dur, where when you're doing your site install, again of a profile, you can specify where your config is stored. The problem with this is it also has problems with config created by the profile and it's being deprecated for a Drush 9. So if you're using this, try to get away from it, try the config installer profile. Okay, if you really have to, if you're in a bind and you've got two sites with different IDs, you can make them the same. So you go look in your system site, a config file, and you'll see the very first line is your site UUID and it's that long string. So you can copy that and you can paste it into a Drush config set. So now you go to your other site, you do drush config set system.site UID, paste in that long string, say yes, and now you've just made that site have the same ID as your first site. Definitely doable if you then have to do it config imports to make that the same. Okay, another question I get a lot is when do you do a config import and when do you run updates and what order do you run them? So the order to do things is, let's say you've got some changes to bring in, you do a get pull to pull in all your code changes, including your config, I know I need to update the drush support right now, it only supports drush eight, I'm sorry, so if you've already upgraded to drush nine, none of the drush commands will work. Okay, which is a whole separate problem. Here, yes, yes, I know. Okay, so I've got a few minutes left here before Q and A, I just wanted to cover, kinda have a couple little tips and tricks that I've run into. This is by no means all of them, I'm sure you will tell me your stories of your config horror, but just after building lots of sites, these are things that come up sometimes. Remember in the old features days where a feature was stuck as being overridden? Anybody run into that? And no matter what you did, it's just always said overridden. Well, we still kinda have that in Drupal eight, like Drupal eight hasn't like magically solved all the world's problems, they're just different. You can have something where every time you do a config export, it exports it again and you're like, wait, it's the same, are you exporting it again? Like you import it and it says, yes, I'll change that and you export it, it's like, yes, I'll change it and it's like this thing is stuck. Like Drupal doesn't know that it's really been exported. Oh, I'm sorry, I'm on the wrong slide. So when you export, every time the config gets re-exported, this can happen sometimes with your entity view modes. So it's usually fields in your view mode and what you still can do, and it's usually complicated as to why Drupal thinks it's bad, but the way you can fix this, and it's usually different developers that have done the same thing at the same time, you can do this trick with config delete. So take a look at the Drush. We talked about config set before to set the UID. There's also a config delete. It's not as bad, and I hate to say this, but I don't think it's as bad as people think it is. This is kind of what we were talking about before. Drupal won't actually delete your content. So if I go into, say, Drush config delete and I delete a field, that might sound horrible, but the fields data is actually still in the database. All the tables are still there. And now I can do a config import and restore that field and everything's fine. So if you get this thing where a field is stuck and it won't revert or it keeps importing and exporting all the time, try deleting it and then doing an import and see if that fixes it. A lot of times that will. That's also, like I said before, how you fix the cardinality where the UI won't let you change it. Or I think actually it does, and I think they fixed it. But if you have these kind of schema changes where the Drupal UI won't let you change something, just go in, edit your config file manually, delete it, re-import it. This one I was talking about first, the other slide. So config versus content, just be aware that there's still this gray area that not everything in Drupal that you might like to be config is considered config. So like menu links, menu links are content. Blocks that you create, if you create a custom block, it says I wanna say welcome user on every one of my pages. So I go and I create a custom block, say welcome, that's actually considered content. It's not exportable, or it's exportable, but it's not gonna be in your config sync directory. So if you run into those cases, a good module for this is the default content module, specifically for blocks. If I create a block that has some text I wanna put on every page, and I wanna put that basically into code, I can use default content to export that block entity as a JSON file, and then put that JSON file, obviously in my code, in my code repo, and then I use a Drush command called default content import all, and it will actually import that JSON file and it will create that content. And you can do that for nodes or for blocks, for any kind of entity that you want. For things like menu links, taxonomy terms, I tend to use the migrate module and the migrate CSV source plugin. So now I can just have a CSV file that says, like here's my client's taxonomy terms, and it just creates those. And now I can run the migrate script, I can roll it back to delete them, rerun it if they add new ones. That works really well for menus and taxonomy terms. Okay, we talked about that. Some other possible config modules, there's actually a lot of config modules, and I kinda stopped here. The two useful ones, the one really useful one that I've definitely used is the config read only. Clients find this really nice on their production site because they can guarantee that there's absolutely no way that someone's gonna change something in the UI and get it exported to the code. If they mess it up in the UI, you can just do a config import and you're back to where you were. So read only is really useful for that. And I think actually Aukria might do that by default. This other one is interesting, config suite. I've just started dabbling in, it was brought to my attention a few weeks ago. It kinda scares me to death, but they say it's good. What this does is, why do config import and export at all? Why not have it automatically be that when I save something in the UI, it automatically exports it. And when I do a get pull and get new config, it automatically imports it. And then I don't have to do any drush commands at all. Well, that'd be great to not have to do any drush commands at all. Maybe try it, let me know what your experience is. For me, I like to look at my stuff and see my changes. The idea that I might be working on something and then it magically imports and my stuff's gone, like I worry about this. But it apparently has really good support for config split as well. So, might be something to take a look at. So, to summarize, stop using features. Use normal config export, config import, get used to the new workflow. Use config split for your environment specific config. You're gonna see config split as part of this CMI 2.0 initiative likely move into core at some point. Use config installer if you need to clone a site and build it from config. You'll likely see that going into core at some point in the future. Get used to managing all your config with git and manage all your changes. Like this config becomes no different from code. Hopefully you're used to using git to manage your code. And it's no different here. If you wanna see what's overridden, you do a git diff after you undo an export. That shows you what's being overridden. If you want to revert stuff, you do a git pull and config import. So just get used to using the git tool. Feel free to play with config actions if you think you wanna generate config and use templates. Don't be afraid of YAML files. One thing you'll notice in Drupal 8 is it's fine. Go, those YAML files live in your config default directory. They're part of your code repo now. You're not afraid of editing PHP code. So why are you afraid of editing the YAML file? You wanna change the site name? You don't need to go to the UI and put it in the box. Just go to the system site YAML file and change it right there. Now you'll hate me for that when you go edit one of those files and get yourself in trouble and change it to something. And now suddenly you've added a comma or something and now the YAML parser complains and won't import. But we're learning, right? So, but learn, take a look at those YAML files. There's some fascinating stuff. Some files are better than others but you can definitely hand edit those if you need to or move them around and play with them. And then yeah, stay tuned for CMI 2.0 that Dries talked about. I think hopefully within a year or so you'll see some improvements to the whole system so we don't need necessarily all of these extra contrib modules. So with that, thanks. And I'm happy to take questions in the small time we have here. Also wanted to give a shout out. Feel free to join us for contrib sprints on Friday and please go review the session. I look at all the reviews that people give and all the feedback and I love to get better at this so definitely sending your feedback and thanks. I have a question? Yes. Oh, good. Okay, we have a mic. Oh, awesome, real. Okay. My question's about the layout initiative and blocks being placed and field layouts and how blocks are both config and content and how all that works together with configuration. So I haven't tried it with the latest 8.5 stuff. I have to admit, which looks awesome. And I tend to be a panel's, panelizer guy right now but I know it's the same developers working on that so they're doing things in similar ways. Layout is still considered config. So the fact that a given block is on the left or right, like you'll export that layout as config just like you do now. Now, sometimes that will have UUIDs of blocks in it and you have to again be careful as to whether that block is a piece of content or not and make sure you're really working with config blocks. But the layout itself and if you drag stuff to the left or the right or add something, that should all get exported to config. Okay, so it'll really work basically kind of the same way, I guess, with blocks still being kind of... Yeah, I don't think blocks aren't changing. This is just a way to organize the blocks. Okay. Yeah, thanks. Yep, next. Yeah, hi. Thanks for all your work on content on configuration management over the years. So we're in this a little bit of a weird space right now with media coming into core and it's leading some configuration issues that I've been trying to deal with where some of the media core in stable, sorry, in standard profile kicks in from the optional folder so that when I'm trying to create a module that's just the way that I typically configure media. So the error comes up when it tries to enable that module that has that configuration that already exists in the active configuration. And so I've been talking to folks, the answer so far I've gotten, the best answer seems to be, well, maybe it should be an install profile, if you're gonna keep reusing that. But that, to me, isn't a good argument because a lot of people just wanna be able to drop in a media configuration or some other set of configurations. So I'm curious, I do have a workaround for it that involves the hook install, loading configuration files, YAML in there, and then loading up a config object and saving it. So that works, but it feels a little hacky, and so I'm wondering. Yeah, the optional stuff, I mean we've had troubles with this in features too, and we actually, in a way, kind of stopped supporting it and we just tell people to, instead of putting it in the optional directory, put it in the install directory, and then tell the person they just need to have media module installed. It comes up with views too of, you know. Right, but it box there and says it already exists in the active configuration. It won't actually import. So with features, features will get around that and will allow it to exist. And if you use config installer, config installer won't botch with that. So it's only if you try to enable the module normally, because yeah, normally it's not gonna let you install a module. So that's one of the reasons we had features was to get around that, but then if you're not putting the config in the module, like if you get used to this idea that the site owns the config and it's all in the default directory, then there's no config in your module. It's all coming from the default directory and it can import that just fine. So that's kind of going back to the profile of yeah, you create a profile and you put everything in the config sync directory and you install the profile at once rather than trying to turn on this one module at a time. But definitely the optional config is where there's still hiccups, yeah. Okay, so you would just recommend creating the config and then throwing it into your default folder. Yeah. Okay, thanks. Hey Mike, thank you for the great talk. The thing that I really love about features is it allows me to organize config into little packages that are, you know, make sense. Is there a way to do that now with this? It seems to be all or nothing or go through things when you start committing and figure out which ones you want to add or not. Yeah, because the problem is it is kind of all or nothing. So let me give you an example. This is my, this actually came up on a client project. So you have an article and a blog content types. And your client says we'd really like to show related content on the page. So we want to show the article and then over in the right sidebar we want a view that shows related stuff, okay? So this is a multi-value entity reference field, right? And it's in any reference field that can reference any content because articles might have related blogs, blogs might have related articles. When you export this, if you go look at the export of that entity reference field, it depends on blog and article. But article has that field and blog has that field. And so you end up with really a circular reference, okay? No way of exploring that with features is going to really help you because one's going to be dependent on the other, which is dependent on the other, there's no order you can enable that. The only way to do it is if it's in one giant directory and it all gets imported at the same time. The only way to get around it with features is actually if you make the content type itself a separate feature. So now you have the content type feature, the field storage feature, the field instance feature for both article and blog. You've got six modules now. Just throw it in, just put it in one directory rather than having like one per. So it's like, yeah, I feel you, I wanted to organize too, like this is why we write modules, right? We don't have all of our code in one giant PHP directory. You know, we have it separated into modules. We have classes. Hopefully we'll have a way to figure it out, you know, in the future of some way of organizing, maybe subdirectories or something. But for now, really the idea that you can organize it really only works for the simpler websites. You know, yeah, simple content types, it kind of works. But it takes a little bit to get used to it, but play with it for a while and you actually, like, I don't miss it that much. Right, so the process is, or the best practice is pull a fresh database down from prod and then do your changes and then export them and don't mix, you know, potentially take different JIRA tickets into one, into one export. I think I'm about to be told that we're done. Maybe ask the floor, we can talk in another session in a few minutes. Thanks a lot.