 Can you hear me OK? All right. Yeah, so I'm going to be talking today about something that's probably running in every Linux laptop and server as well, which is a system D and D bus. So a little bit of background myself. My name is Leonid. I work at Dropbox on the infrastructure team and does a deal a lot with Linux and servers and all the infrastructure. And one thing I keep noticing is that when I go to servers, we maintain. I always see system D and D bus running there. So they're like system D. They manage new services. But I was always curious, what is D bus? What's it doing? Can I use it for something? And I start looking into that a few months ago and start exploring. Can I do something with it? Can I use it for some of my services? Can I use it to programmatically do some tasks? And yeah, so this talk is the result of this exploration, really, is to take a look at what's going on there. So I'll start by just describing the scope of this and then go briefly through D bus and system D. Then see how really linear distributions laid out the configuration for that. It's very shortly about that. And then the main point here is to show how a Go developer can interact with these services and build something out of that. And at the end, it's sort of wrapped up with, is it worth it? Or what is it good for? So yeah. So we'll be looking at system programming. So this area, as Miky Pide has it defined, is software that provides services for other software. So this is not applications, not user-facing services. This is more like a back-end infrastructure components. And I'm going to be looking at Go developer point of view. So it's developed test debug cycle is to how to get productive with these tools with system D and D bus. Not really how to configure system D itself, how to manage D bus, how to manage containers, et cetera. And again, this is modern Linux. So think about most stable distribution, Linux distribution. I used Ubuntu 18.04 as an example here. But I'm very sure Fedora and other distributions, they have the kind of similar setup, which is standard. So let's get started. What is D bus? So first of all, is a specification. So free desktop.org is a initiative. As a Linux desktop defines the set of standards around Linux desktop. So D bus came around 2003. So this is a very, very long time ago. So JSON came around this time. So you can just kind of put things in perspective. And I sort of divide this specification in two parts. One is core protocol, which deals with a type system, wire format, and certain core pieces of the protocol. And the second one is the message bus abstraction. This is where it's actually used as a message bus supports naming, well-known buses, meshes, routing, and standard interfaces. So we'll be looking into that. And there is also a reference implementation, which is used pretty much everywhere. LibDBus implements the core protocol part. And DbusDemon implements the Dbus abstraction. So this is what you get on your Fedora or Ubuntu. There is many alternatives implementation of the core protocol. There is SD bus from SystemD. There is GoDBus, which we'll be using today. There are not that many implementations of message buses. There's Dbus Broker, but we're not going to look into that. So what is SystemD? It came out 2010, 10 years ago, as a CSV niche replacement, but expanded much more. So I'm only briefly touching this because there's so much to go into that. Again, the goal here is to really show how to use Go to interact with SystemD. And many mainstream Linux distributions actually have that by default configured, including there's Linux from scratch, which is interesting. It's basically just a document. And even that has SystemD version. And also all the SystemD APIs, they provide it through Dbus itself. So you can read the code of SystemD to kind of understand what's exactly there, but it's very powerful. And to start with, we need to first understand the how Linux configures that, how distributions configure SystemD and Dbus. And this is like we're going to be using today something called Linux Session. This is really how Linux distribution configures all the environment. So here you can see the output of SystemD CGLS, which, so SystemD partitions your user space into a set of namespaces. And they're nicely grouped into hierarchies here. This is Linux Session hierarchy. User at 1,000 is basically what everyone would get if there's SSH on the basic Linux. This case is Ubuntu. And this is already enabled by default. Highlighted there is the two components. You can see I have SystemD Manager running already. So this is interesting, because SystemD can run many SystemDs on the system. So this is sort of like a delegation. They run a separate user manager for every user in the system. And you can see also DbusDman runs a separate call session bus, again, under generic user. And this is how it looks like from the process point of view. Like if I look all the processes, so I'm using RayGrant here and the generic Ubuntu image around PS3, which shows me all the processes for user RayGrant. And you can see SSHD bash and then the command. But then the highlight, again, I have a SystemD and Dbus. So I haven't started that manually. It was already there. So it's there by default. So I don't have to do anything. Also I don't need a root to do that. So it's kind of, this setup is rootless, sort of. I don't need any extra permissions to do anything. Everything is already set up, configured for me. So from go point of view is, it looks like this. So we're going to be dealing with the writing code in go process there on the left. We're going to be using two libraries, goDbusDbus and core OS, goSystemD, which is a library in top of goDbus. It provides a more go, kind of go flavored abstractions in top of Dbus. The central component is DbusDemon itself that implements the message bus obstruction and it uses the reference implementation libDbus. On the right we have a SystemD which uses a different implementation of the bus library called SDbus. All these three components communicate through a shared Linux domain socket. So it's a standard, it's part of the specification. It's called a session bus. So basically it's a, it's a Unix domain socket. It's like a single file on the file system. Not nothing special about it. Again, I don't have to set it up. It's already there on most of the default distributions. So let's start with Dbus. So the thing about is when I started looking at that, there was kind of quite steep learning curve here is if you compare that to GRPC, for example, it's like most recent version, GRPC or even like a REST API. In REST you have a simple URL to identify what you wanna do, what's kind of method you wanna call and GRPC sort of abstracts that all away from you completely. In Dbus it's a bit different. It's very, it comes from the ages before web I would say. So if you heard something called CORBA and this object oriented abstractions from the 90s, so this is where it's coming from. The terminology boils down to really like three things. So you have a bus, which is basically, it's a process. So you connect to, we can use the Dbus demand. It's a process. So it's kind of like address. It could be Unix socket, it could be TCP, which is not quite used often, but still. Connection is identified by name. You can think about it as a DNS name. The object, and this is kind of the part of the object interface and the member. This is really three things kind of combined. You can think of it as a one thing. So it basically tells you what the kind of URL is, which is the object. What type of interface method you're gonna call. And the method has to be a part of some interface called the member here. So object interface and a member you can think about as a URL based in a REST kind of JSON RPC or something like this. There are some tools. Again, these tools are available by default on most of the Linux distributions. So you have Dbus send. It's a convenience CLI tool. If you want to interact with Dbus, you can send a command here in the example we can see I'm using session bus. This is again, like this is a user's private session that's configured everywhere. And I'm calling a method on the default destination which is org for desktop Dbus. The object path is slash, which is kind of root of the hierarchy. And then the method is list names. It shows me what connections available on this bus. So I see Dbus, I see system D and then I see two private connections which come from the Dbus send itself. There's another tool, bus cuddle. It's part of system D is also available by default. It's part of system D package. It's pretty much can do the same as Dbus send but it's more like a terminology is a bit different. So in Dbus send, you use session. In Dbus cuddle, you use user to kind of, there are two commands, tree, which lets you list all these object hierarchies that available under for certain service name. There is also introspect that shows you what the actual interface is available. What can you do with that? This is all useful. We're gonna be using this with system D. So let's start with how to use that from Go. So how do you use Dbus from Go? There's library, Go Dbus bus. It's native Go library. There's no, it doesn't depend on LibDbus. There's no Cgo. It's very kind of simple library in terms of, it just does the message serialization, deserialization and provides some of the wrappers on top of that. So what we have here is highlighted in, you connect to session bus, you create an object, instantiate connection object. It identifies where you're gonna be connecting to. And then you call a method. And then you need to deserialize the result. So serialization in deserialization, it uses reflection a lot. So it's kind of like a bit of a pain point because that thing panicked on me a lot when I tried to, when you try to deserialize something in the wrong format, it was just panic. So you have to be careful with that. It's easy to make it panic. So Dbus message format is a binary format. It's a kind of interesting one. So you have every type release prefix with the ASCII character. So here they use the call it signature. So for example, why this signature translates as Y means byte, U means you int, A means array and parans means it's a struct. So it's kind of easy to understand but yeah it's not what you see in very often these days. How to construct a message in go? Yeah, this library has this message type as a type. If you wanna make a method call, you call it type method call. And then it takes a bunch of headers. And the headers really set the destination, the, what the method is, what the interface is. And then the body of the message is, it looks very similar. So all the messages they operate on this generic interface. This is again, like because it's all user reflection, I find it hard to, it's very easy to make a mistake and then this thing will panic or you'll get something not that you wanted. But yeah, so briefly about introspection. So when you wanna call some method in Dbus, you need to know which parameters it's going to take. The way to actually implement that, it uses XML. So it's really, it's a standard interface and you have to define this XML format. The format is easy, you have an interface and then you have a method, then you list your arguments. So you can think about it as a sort of like, if you use GRPC, this is like what you define in protobufs. The problem is that it doesn't generate anything out of that. So you still have to kind of code by hand manually all the wrappers itself. So if you want to export an object, for example, this is, I wanna run the bus service as a worker, a generic worker. Export this object, so first of all, there's not like a request handler, I just export the object and all the methods, all the public methods will be available on the bus. So three lines, I export object, I also need to export this XML definition and then I need to request a name which is kind of like a DNS name under which name will be available, my object. And this is how it's implemented, so you have to kind of hard code XML, beat and error code and then all the public method will be exported. You can configure that, but the point here is it's a regular go method. The only difference is if you return an error which is quite common in go, here you have to do different, it has to be a debust error, so it's encoded properly. There's another concept in debust called signals, it's implement one to many publish subscribes, so this is where it gets to useful parts actually, you can implement publish subscribes quite easily and it's async and you have to kind of filter which messages you want to get on the bus, it's possible to get all the messages, but yeah, you have to configure that first. There are some best practices, they're, I found these two nice pages, one is a Chrome OS apparently, either used or uses the bus for everything and they have this nice page where they say it's like basically, avoid every advanced feature of the bus, avoid properties, complex object hierarchies, consider using protobufs instead of complex messages, so you don't have to deal with that XML definitions and don't use the bus service activation, this is kind of, I think it's a legacy feature but you can start a service through the bus, I guess, and then there's another article, it's about how to version, it's essentially, it's same as GRPC, once you made it an interface public, you can't change it, you can only extend it but you can't really change anything that's already available. So let's go to system D, so we know a little bit about the bus, so system D, very powerful, it's basically how the Linux user space looks these days and to use it, you have to understand the bus, you can of course call the sub process, you can exec and that's kind of ST, so yeah, so D-Bus interface, it's very powerful there, so system D really, high level, it's system D operates in units, it can run jobs that transition these units through a set of states, so units are really stateful and changing of states, you can set up D-Bus signals to receive all the signals when your service start up, shut down, something happens to that, there are three commands really to start exploring the API, is the first one is tree, at least all object hierarchy, introspect, see what's available, what interface is available and then the last one is actually see which units implement what interfaces, so how do you use that in Go? So CoroS, I think this is the part of the, they were building a container engine on top of system D and as part of this, they build this library, Go system D, it's a wrapper on top of D-Bus, it has some helpers, but the essence is just, it's a thing wrapper, so very simple how to list all the units currently available in system D, connect to the user connection, so you don't have to use root for that, so and then just call list units and this is super, super easy, how to create a transient unit and this is where it's actually like more like exploration area, I'm trying to see, can I use system D to simplify some of the infrastructure related like very low level, system level automation I'm working on and the one nice thing is system D has this concept of transient unit, it's a unit created dynamically, it's not persisted on disk and you can run it through CLI, system D prizes your local system D run dash dash user and you can run like an end of command in a transient unit and then you can see all the output of that, so having example, this is how to do that in Go, very easy, you connect to the bus, then you have to create a job, basically it's a, you start a transient unit and it takes a list of properties and this is what you want to run under this unit, this could be any command or it could be any service for example, if you wanna run a Go playground or something like that, so you can start that and then you have to wait on the channel to when the job is completed, so it means that the task or the service is activated. So this is really a raps to talk and I have like pros and cons, you can read through that but yeah, this is the end, it's kind of very stable but the D bus part is really, yeah, it's a lot of legacy stuff and yeah, it's a steep learning curve as well. Yeah, this is it.